标签:无效 函数重载 sam error blog .exe 种类型 type erro
1. std::conditional
(1)原型:template <bool Cond, class T, class F> struct conditional;
//根据条件获取T或F类型 template<bool Cond, class T, class F> //泛化 struct conditional { typedef T type; }; template<class T, class F> //偏特化 struct conditional<false, T, F> { typedef F type; };
(2)说明:
①当cond为true时,conditional::type被定义为T类型。
②当cond为false时,conditional::type被定义为F类型。
【编程实验】std::conditional
#include <iostream> #include <typeinfo> using namespace std; int main() { typedef std::conditional<true, int, float>::type A; //int typedef std::conditional<false, int, float>::type B; //float typedef std::conditional<is_integral<A>::value, long, int>::type C; //long typedef std::conditional<is_integral<B>::value, long, int>::type D; //int //比较两个类型,输出较大的类型 typedef std::conditional<(sizeof(long long) > sizeof(long double)), long long, long double>::type max_size_t; cout << typeid(max_size_t).name() << endl; //long double return 0; }
2. std::enable_if
(1)enable_if的作用:
①当某个 condition 成立时,enable_if可以提供某种类型
②具备限定模板参数的作用,可以在编译期检查输入的模板参数是否有效。
③可以用来控制重载函数是否可用,以实现强大的重载机制。
(2)std::enable_if的原型
①原型: template<bool cond, class T = void> struct enable_if;
//enable_if的可能实现 template<bool Cond, typename T = void> struct enable_if {}; //注意,没有type类型 template<typename T> //偏特化,注意T的默认值为void struct enable_if<true, T> { typedef T type; };
②在 condition 为真的时候,由于偏特化机制,第2个结构体模板明显是一个更好的匹配,所以 std::enable_if<>::type 就是有效的。
③当condition 为假的时候,只有第一个结构体模板能够匹配,所以std::enable_if<>::type 是无效的,会被丢弃。同时,编译器会报错:error: no type named ‘type’ in ‘struct std::enable_if<false, bool>。
【编程实验】利用std::enable_if检查模板参数
#include <iostream> #include <typeinfo> using namespace std; //1. 模板参数只能是arithmetic(整型和浮点型) template<typename T> typename std::enable_if<is_arithmetic<T>::value, T>::type foo1(T t) { return t; } //2. 限定入参类型: template<typename T> //注意限制的是foo1的第2个形参,只能是整型 T foo2(T t, typename std::enable_if<std::is_integral<T>::value, int>::type = 0) { return t; } //3. 限定模板参数T的类型 (注意限制的是模板的T参数:为intergral类型)、 // 如果T是integral类型,is_integral<T>::value为false,enable_if<false>::type将报错 template<typename T, class = typename std::enable_if<std::is_integral<T>::value>::type> T foo3(T t) { return t; } //4. 类模板特化时,参数的限定 //前向声明,A为类模板 template<class T, class Enable = void> class A; template<class T> //模板特化 class A<T, typename std::enable_if<std::is_floating_point<T>::value>::type> //对模板参数的限定 {}; int main() { //1. auto r1 = foo1(1); //返回整数1 auto r2 = foo1(1.2); //返回浮点数1.2 //auto r3 = foo1("test"); //error //2. 限定入参类型 foo2(1, 2); //ok //foo2(1, ""); //error,第二个参数应为integral类型 //3.限定模板参数 foo3(1); //foo3(1.2); //error,模板参数的类型应为integral类型z z //4.类模板特化时,参数的限定 A<double> a1; //ok,先匹配特化模板,所以a的类型为A<double, double> //A<double, double> a2; //error, 显式指式两个参数。因此匹配的是第1个模板,但由于这里只是声明 //而未定义类(注意class A和class A{}的区别),所以会报A是个未完整类的错误。 //A<int> a3; //先匹配特化模板(失败)。再匹配A<int, void>模板,但由于class A只是声明,会与a2一样。 //的错误。 return 0; }
(3)注意事项
①T的默认值为void类型,即enable_if的第2个模板参数不指定时,当cond为真,默认会获取到的类型为void。
②当cond为假时,由于std::enable_if<>::type是无效的,因此编译器会报错。
【编程实验】利用std::enable_if根据条件选择重载函数
#include <iostream> using namespace std; //利用std::enable_if根据条件选择重载函数 /********************************************************************************************/ //利用std::enable_if来选择重载的模板函数foo //(注意,两个模板函数仅返回值不同!而模板参数从形式上看虽然相同,但实参推导后T类型是不同的!) //1. 模板函数的参数相同,返回值不同函数的重载。(注意,实际推导后形参其实是不同的!) template <class T> typename std::enable_if<std::is_arithmetic<T>::value>::type //T为arithmetic类型时,返回值void foo(T& t) //两个foo函数,模板参数相同。但实际推导后这里是arithmetic类型。 { return; } template <class T> typename std::enable_if<std::is_class<T>::value, T>::type& //T为class时,T& foo(T& t) { return t; } //2. 模板函数的形参相同,返回值相同的函数重载。(注意,实际推导后形参其实是不同的!) //函数功能:将输入的参数转为string类型 //(对于arithemic类型调用std::to_string(t),对于string类型返回其本身) template<class T> typename std::enable_if<std::is_arithmetic<T>::value, string>::type //返回值string toString(T& t) { return std::to_string(t); } template<class T> typename std::enable_if<std::is_same<T, string>::value, string>::type //返回值 toString(T& t) { return t; } class Test{}; /********************************************************************************************/ //3. 可调用对象包装器的实现 //3.1 无返回值的情况: template<class FT,class...Args> auto call(FT&& f, Args&&...args)-> //返回值为void typename std::enable_if<std::is_void<typename std::result_of<FT(Args...)>::type>::value, void>::type { f(std::forward<Args>(args)...); } //3.2 有返回值的情况 template<class FT, class...Args> auto call(FT&& f, Args&&...args)-> //当f有返回值时,则返回f原来的返回类型 typename std::enable_if<!std::is_void<typename std::result_of<FT(Args...)>::type>::value, typename std::result_of<FT(Args...)>::type>::type { return f(std::forward<Args>(args)...); } //3.3 万能包装器(统一以上两种情况) template<typename FT, class...Args> auto FuncWrap(FT&& func, Args&& ...args)->decltype(func(std::forward<Args>(args)...)) { return func(std::forward<Args>(args)...); } int func(int a, int b) { cout << "int func(int a, int b):" << a + b << endl; return a + b; } int main() { //1. 选择foo重载函数(返回值不同) int x = 1; foo(x); //匹配第1个模板,返回void类型 Test t; foo(t); //匹配第2个模板,返回Test& //2. 选择toString重载函数(返回值相同) cout << toString(x) << endl; string s("abc"); cout << toString(s)<< endl; //3. 可调用对象包装器 auto lda = [](){cout << "do anything you want!" << endl;}; call(lda); //无返回值 call([](int a){cout << "a = " << a << endl;}, 1); call(func, 1, 2); //带返回值 FuncWrap(lda); //无返回值 FuncWrap(func, 1, 2); //带返回值 return 0; } /*输出结果 e:\Study\C++11\19>g++ -std=c++11 test3.cpp e:\Study\C++11\19>a.exe 1 abc do anything you want! a = 1 int func(int a, int b):3 do anything you want! int func(int a, int b):3 */
标签:无效 函数重载 sam error blog .exe 种类型 type erro
原文地址:http://www.cnblogs.com/5iedu/p/7782291.html