std::result_of 模板参数只能是函数指针类型,函数引用类型,function-like class(仿函数类)三者之一;不能是函数类型,函数数类型是不具有调用call特性的. result_of内部是把函数调用拆成函数类型和函数参数两部分处理的
int fn(int) {return int();}
typedef int(&fn_ref)(int);
typedef int(*fn_ptr)(int);
struct fn_class { int operator()(int i){return i;} };
int main()
{
typedef std::result_of<decltype(fn)&(int)>::type A;
std::cout<<type_name<A>()<<std::endl;
typedef std::result_of<fn_ref(int)>::type B;
std::cout<<type_name<B>()<<std::endl;
typedef std::result_of<fn_ptr(int)>::type C;
std::cout<<type_name<C>()<<std::endl;
typedef std::result_of<fn_class(int)>::type D;
std::cout<<type_name<D>()<<std::endl;
}
---------seprator---------
void func(auto a = 1){}; //error: auto不能用于函数形参,哪怕是带默认参数的形参
struct MyStruct
{
auto var = 1;
//error: auto不能修饰类或者结构体中的非静态成员
static auto var2 = 2;
};
template<class T>
struct Bar{};
int main()
{
int arr[10] = { 0 };
auto a = arr; //OK: a ->int *
auto r[10] = arr;
//error : auto不能定义数组
Bar<int> bar;
Bar<auto> bb = bar;
//error: auto 不能作为模板参数
return 0;
}
auto的使用限制为:
1、auto不能作为函数参数。
2、auto不能修饰类或者结构体中的非静态成员变量
3、auto不能定义数组
4、auto不能推导出模板参数
-------seprator---------
#include <type_traits>
auto call(const
auto& f) -> typename std::result_of<decltype(f)()>::type
{
return f();
}
int main()
{
return call([] { return 0; });
}
Neither gcc-4.9.2 and gcc-5.0.0 compil!!!!
error原因: auto 不能做模板参数
//error
auto call(const auto& f) -> typename std::result_of<decltype(f)()>::type
{
return f();
}
//success 1
template<typename F>
auto call(const F& f) -> typename std::result_of<decltype(f)()>::type
{
std::cout<<type_name<decltype(f)>()<<std::endl;
std::cout<<type_name<F>()<<std::endl;
return f();
}
//success 2
auto call(const F& f) -> typename std::result_of<F()>::type
{
std::cout<<type_name<decltype(f)>()<<std::endl;
std::cout<<type_name<F>()<<std::endl;
return f();
}
//success 3
template<typename F>
auto call(F const& f) -> decltype(f())
{
return f();
}
int main()
{
return call([] { return 0; });
}
-------------output----------------------
main::{lambda()#1} const&
main::{lambda()#1}
-------seprator---------
Anyway, on gcc 4.5, result_of is implemented in terms of decltype:
template<typename _Signature>
class result_of;
template<typename _Functor, typename... _ArgTypes>
struct result_of<_Functor(_ArgTypes...)>
{
typedef decltype( std::declval<_Functor>()(std::declval<_ArgTypes>()...) ) type;
};
//error
template <class F, class R = typename result_of<F(char)>::type>
R call_fun(F& f)
{
std::cout<<type_name<F>()<<std::endl;
std::cout<<type_name<F&>()<<std::endl;
return f();
}
int answer(char c)
{
return 0;
}
int main()
{
call_fun(answer);
}
//success
template <class F, class R = typename result_of<F&(char)>::type>
R call_fun(F& f)
{
std::cout<<type_name<F>()<<std::endl;
std::cout<<type_name<F&>()<<std::endl;
return f();
}
int answer(char c)
{
return 0;
}
int main()
{
call_fun(answer);
}
/**************************正确的方式************************************************************/
#include <iostream>
#include <type_traits>
double f(int i)
{
return i+0.1;
}
struct F
{
public:
double operator ()(int i) { return i+0.1; }
};
int
main(int, char**)
{
std::result_of<F(int)>::type x;
std::result_of<f(int)>::type x; //错误的用法
//typename std::result_of<decltype(&f)(int)>::type x; //正确的方式1
//typename std::result_of<decltype((f))(int)>::type x; //正确的方式2, decltype((f))会返回一个引用
x = 0.1;
std::cerr << x << std::endl;
}
struct AA {};
int foo(AA x)
{
return 0;
}
template<typename T>
void Test(const T& t)
{
decltype(std::declval<T>()(std::declval<AA>())) i1 = 1;
typename std::result_of<decltype(&t)(AA)>::type i2 = 2; //正确的方式1
typename std::result_of<decltype(t)(AA)>::type i2 = 2; //正确的方式2
typename std::result_of<const T &(AA)>::type i3 = 2; //正确的方式3
}
int main()
{
Test(foo);
return 0;
}
g++ tpl.cpp -std=c++11 -g -fno-elide-constructors -O0