使用函子的返回类型来声明模板方法的返回类型,不需要decltype
Using the return type of a functor to declare return type of a template method, without decltype
我希望在调用模板成员函数时避免指定返回类型的需要。"decltype"关键字与"auto"关键字结合可以实现这一点,但不幸的是,我们没有一个c++ 11编译器来支持所有我们需要支持的平台。用类型限定模板方法应用程序也可以,但是要求调用者……使用类型限定模板方法。
是否可以使用一些模板魔法?boost 1.48在这里提供任何帮助吗?
我们的实际代码利用了boost::thread、boost::packaged_task和boost::unique_future,但这里有一个人为的例子:
#include <functional>
#ifdef WONT_COMPILE
struct WrapNoDecltype
{
WrapNoDecltype() {}
template<typename F>
std::result_of<F>::type // warning: 'std::result_of<_Fty>::type' : dependent name is not a type
operator()(const F& f)
{
setup();
std::result_of<F>::type result = f();
teardown();
return result;
}
void setup() { }
void teardown() { }
};
#endif
struct Wrap
{
Wrap() {}
template<typename F>
auto operator()(const F& f) -> decltype(f())
{
setup();
typename std::result_of<F()>::type result = f();
teardown();
return result;
}
void setup() { }
void teardown() { }
};
struct WrapWithReturnType
{
WrapWithReturnType() {}
template<typename RetType>
RetType
apply(const std::function<RetType(void)>& f)
{
setup();
RetType result = f();
teardown();
return result;
}
void setup() { }
void teardown() { }
};
int answer()
{
return 42;
}
int main()
{
Wrap w;
WrapWithReturnType wwr;
#ifdef WONT_COMPILE
WrapNoDecltype wna;
#endif
int i = w(answer);
int j = wwr.apply<int>(answer);
#ifdef WONT_COMPILE
int k = wna(answer);
#endif
return 0;
}
struct WrapNoDecltype
{
WrapNoDecltype() {}
// version for function references
template < typename Res >
Res operator()( Res(&f)() )
{
setup();
Res result = f();
teardown();
return result;
}
// version for everything
template < typename T >
typename std::result_of<typename std::decay<T>::type ()>::type
operator()( T const& f )
{
setup();
typename std::result_of<typename std::decay<T>::type ()>::type result = f();
teardown();
return result;
}
void setup() { }
void teardown() { }
};
正如Yakk指出的那样,通过合并decay
,第二个版本总是有效的。第一个版本要简单得多,但只适用于传递函数引用。
当然,您也可以使用boost::result_of
或std::tr1::result_of
据我所知,如果我们修改您的调用以包含&
操作符,原始代码中唯一的错误是在谈论依赖类型时缺乏typename
,以及在调用std::result_of
时缺乏参数列表:
struct WrapNoDecltype
{
WrapNoDecltype() {}
template < typename T >
typename std::result_of<T()>::type operator()( T const &f )
{
setup();
typename std::result_of<T()>::type result = f();
teardown();
return result;
}
};
然而,std::result_of
是一个c++ 11特征类,所以如果你的编译器不支持decltype
,它可能不正确地支持std::result_of
。
std::tr1::result_of
可能有阻止上述工作的怪癖。
在野外,std::result_of
在函数指针类型上的使用:http://ideone.com/dkGid8
正如@DyP所指出的,这只有在使用&f
而不是f
调用时才有效。要解决这个问题,像这样使用std::decay
:
struct WrapNoDecltype
{
WrapNoDecltype() {}
template < typename T >
typename std::result_of<typename std::decay<T>::type()>::type
operator()( T const &f )
{
// setup()
typename std::result_of<typename std::decay<T>::type()>::type
result = f();
// teardown()
return result;
}
};
int foo() { return 7; }
int main()
{
WrapNoDecltype test;
int x = test(foo);
}
将函数类型转换为函数指针类型。
这是必需的,因为std::result_of
滥用c++语法。std::result_of< Func_Type ( Args... ) >
实际上是对返回 Func_Type
并接受(Args...)
的函数类型进行操作。然后它说"如果我们将Args...
应用于Func_Type
会怎么样?"当Func_Type
是函数的实际类型时,这将不起作用,因为不允许返回函数的实际实例。
std::decay
将作为函数类型的Func_Type
转换为指向同一类型函数的指针,这是函数可以返回的东西。您可以像调用实际的函数一样调用指向函数的指针,因此也没有什么害处。
- 将返回类型推断为模板参数类型方法
- 我如何根据某些模板参数影响模板类方法的返回类型
- 具有协变返回类型的方法在 VC++ 上崩溃
- 如何检查模板类方法返回类型
- 如何使用类型专用化模板方法,该类型本身就是一个模板,其中只有返回类型依赖于模板类型
- 解释C 中三种返回类型的方法
- C++可以返回不同模板化类型的方法
- 如何解决自动返回类型-C++(模板)
- 类成员方法 - 返回类型模板
- C++:使用不同的返回类型模板化虚拟方法
- C++显式返回类型模板专用化
- 使用方法捕获模板化可调用对象的返回类型
- C++ -模板类,其中包含返回模板类型的方法
- 返回类型的C++11 方法模板专用化
- C++中具有多态模板类的未知方法返回类型
- 模板方法中的C++11自动返回类型
- C++绑定返回类型模板参数
- 返回类型模板(enable_if)禁止什么
- c++:继承具有不同(但协变)返回类型的方法
- 为什么c#或c++不能根据返回类型区分方法