我在理解std::result_ofC++ 0x中的需求时遇到了一些麻烦.如果我理解正确,result_of则用于获取调用具有某些类型参数的函数对象的结果类型.例如:
template <typename F, typename Arg>
typename std::result_of<F(Arg)>::type
invoke(F f, Arg a)
{
return f(a);
}
Run Code Online (Sandbox Code Playgroud)
我真的没有看到与以下代码的区别:
template <typename F, typename Arg>
auto invoke(F f, Arg a) -> decltype(f(a)) //uses the f parameter
{
return f(a);
}
Run Code Online (Sandbox Code Playgroud)
要么
template <typename F, typename Arg>
auto invoke(F f, Arg a) -> decltype(F()(a)); //"constructs" an F
{
return f(a);
}
Run Code Online (Sandbox Code Playgroud)
我能用这两种解决方案看到的唯一问题是我们需要:
难道我就在想,唯一的区别decltype和result_of是而第二个不第一个需要表达?
作为理解C++ 0x的练习,我试图创建一个C++类,它包含一些模板化类型的指针:
template <typename T>
class Wrapper {
T *t;
/* ... */
};
Run Code Online (Sandbox Code Playgroud)
在Wrapper类中,我想公开T可以通过Wrapper类实现的任何重载操作符.包装器本身只是将函数调用转发给底层的t对象.
template <typename U>
auto operator+(U &u) -> decltype (*t + u) {
return *t + u;
}
Run Code Online (Sandbox Code Playgroud)
问题在于我不希望Wrapper暴露T可能无法实现的操作员.例如,如果T没有实现operator +,那么Wrapper也不应该公开operator +.
在operator +(以及任何二进制操作)的情况下,一切都运行,因为运算符必然成为模板函数,因此仅在我们尝试调用时实例化,例如,Wrapper :: operator +.
然而,在一元运算符(例如,++)的情况下,没有一种明确的方法来保护运算符,以便在tf实现operator ++时实例化它.例如,这个类中的operator ++的天真实现
auto operator++() -> decltype(++(*t)) {
return ++(*t);
}
Run Code Online (Sandbox Code Playgroud)
无法为不支持operator ++()的T编译.
根据我对标准的理解,如果我们有以下使用Wrapper的代码
class X { };
Wrapper<X> w;
Run Code Online (Sandbox Code Playgroud)
我们将实例化Wrapper和Wrapper :: operator ++()的声明,但不是它的定义,除非我们调用它(或显式地实例化它).通常情况下这是可以的,因为X :: operator ++的使用仅出现在Wrapper :: operator ++()的定义中.但是,由于decltype,我们在声明中使用X :: operator ++,以便typechecker检查是否存在X :: operator ++,从而失败. …