C++14 SFINAE 解援用迭代器。本站提示廣大學習愛好者:(C++14 SFINAE 解援用迭代器)文章只能為提供參考,不一定能成為您想要的結果。以下是C++14 SFINAE 解援用迭代器正文
原問題:編寫函數f(r),若r為迭代器,則前往f(*r),否則前往r。
摘要: 問題:什麼是迭代器?
迭代器是c++中的一個概念,若類型It滿足以下條件,則It為迭代器類型
可拷貝結構(CopyConstructible)
可拷貝賦值(CopyAssignable)
可析構(Destructibale)
左值It對象可交流(Swappable)
std::iterator_traits<It>含如下類型成員:value_type, difference_type, reference, pointer和iterator_category
關於It的左值r,如下表達式合法且具有指定含義:
*r 前往值類型:unspecified 前置條件:r可解援用
++r 前往值類型: It & 前置條件:r可自增
在後續完成中,將放寬迭代器的要求:對左值r,設若*r合法,則r有迭代器類型。意即:
編寫函數f(r),若左值r可被解援用,前往f(*r),否則前往r。
問題剖析:f的前往值類型隨實踐參數而改動。若r為int **類型,至多需求兩個f的重載int *f(int **)和 int f(int *)。需求經過泛型在編譯期依據f的調用生成這些函數重載。
在調用時,重載決議階段需求編譯器選取適宜的函數模板。
若類型T的左值可被解援用,則選取函數模板(1)
template <class T> auto f(T r) { return f(*r); }
template <class T> auto f(T r) { return r; }
如何依據上述規則選取函數模板?
若兩個f模板均合法,則選取模板(1),否則選取合法模板。
合法定義為:r可被解援用。
如何表達優先選取?
經過重載隱式轉換序列分級。使得由模板(1)生成的函數的分級高於模板(2)
如何表達合法性?
經過SFINAE,若r不可被解援用,使得模板(1)替代失敗(substitution failure)。
1 #include <cassert> 2 3 #include <type_traits> 4 #include <utility> 5 6 template <class T> 7 auto f(T x, ...) { 8 return x; 9 } 10 11 template <class T, class = decltype(*std::declval<T>())> 12 auto f(T x, int) { 13 return f(*x, 0); 14 } 15 16 int main() { 17 int x = 3, *p = &x; 18 assert(f(&p, 0)==3); 19 20 return 0; 21 }
注釋:
從略。
FAQ:
尚無。
參考材料:
http://en.cppreference.com/w/cpp/concept/Iterator
http://en.cppreference.com/w/cpp/language/overload_resolution (return type deduction)
http://en.cppreference.com/w/cpp/utility/declval
http://en.cppreference.com/w/cpp/language/overload_resolution
http://en.cppreference.com/w/cpp/language/template_argument_deduction