我想避免在调用模板成员函数时指定返回类型。 '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;
}
答案 0 :(得分:1)
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
。
答案 1 :(得分:1)
据我所知,如果我们修改您的调用以包含&
运算符,原始代码中的唯一错误是在讨论依赖类型时缺少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
作为函数的类型转换为指向同一类型函数的指针,这是函数可以返回的函数。并且你可以像调用实际函数一样调用指向函数的指针,所以也没有任何伤害。