要在编译期决定一个样板仿函数的回返值类别并不容易,特别是当返回值依赖于函数的参数时。举例来说:
struct Clear { int operator()(int); // 參數與回返值的型別相同 double operator()(double); // 參數與回返值的型別相同 }; template <class Obj> class Calculus { public: template<class Arg> Arg operator()(Arg& a) const { return member(a); } private: Obj member; };
实体化样板类 Calculus<Clear>
,Calculus
的仿函数其回返值总是和 Clear
的仿函数其回返值具有相同的类别。然而,若给定类型 Confused
:
struct Confused { double operator()(int); // 參數與回返值的型別不相同 int operator()(double); // 參數與回返值的型別不相同 };
企图实体化样板类 Calculus<Confused> 将导致 Calculus 的仿函数其回返值和类型 Confused 的仿函数其回返值有不同的类别。对于 int
和 double
之间的转换,编译器将给出警告。
模板 std::result_of
被TR1 引进且被 C++11 所采纳,可允许我们决定和使用一个仿函数其回返值的类别。底下,CalculusVer2
对象使用 std::result_of
对象来推导其仿函数的回返值类别:
template< class Obj > class CalculusVer2 { public: template<class Arg> typename std::result_of<Obj(Arg)>::type operator()(Arg& a) const { return member(a); } private: Obj member; };
如此一来,在实体化 CalculusVer2<Confused>
其仿函数时,不会有类别转换,警告或是错误发生。
模板 std::result_of
在 TR1 和 C++11 有一点不同。TR1 的版本允许实现在特殊情况下,可以无法决定一个函数调用其回返值类别。然而,因为 C++11支持了decltype,实现被要求在所有情况下,皆能计算出回返值类别。