我得到了这段代码:
template <class FunctionType> class Entry {
std::function<FunctionType> internalFunction;
template<class... Arguments>
auto operator()(Arguments... arguments) -> decltype(internalFunction(arguments...)){
if (std::is_same<decltype(internalFunction(arguments...)), void>::value) {
internalFunction(arguments...);
} else {
auto result = internalFunction(arguments...);
return result;
}
}
};
Entry类是std::function
的包装器。它适用于所有返回类型,但有一个例外 - void
。我无法让它发挥作用。我也尝试过std::is_void
,对于void(...)
类型的函数,它不会返回true。 std::is_same
也一样。
如何解决这个问题?
答案 0 :(得分:4)
return internalFunction(arguments...);
即使internalFunction
返回void
尝试将结果存储在中间对象中并不起作用,因为您无法创建void
类型的对象,因为它不是对象类型。
您的if
不起作用,因为if
是运行时条件,编译器仍然需要编译条件的两个分支,因此它们必须都是有效的C ++。
如果您需要创建中间结果类型的变量,则不能将该代码用于void
情况。您可以为返回void
的函数编写部分特化:
template <class FunctionType> class Entry {
std::function<FunctionType> internalFunction;
template<class... Arguments>
auto operator()(Arguments... arguments) -> decltype(internalFunction(arguments...))
{
auto result = internalFunction(arguments...);
return result;
}
};
template <class... ArgTypes> class Entry<void(ArgTypes...)> {
std::function<void(ArgTypes...)> internalFunction;
template<class... Arguments>
void operator()(Arguments... arguments) {
internalFunction(arguments...);
}
};
对于返回void
的函数而言,这不起作用,但对于返回void
的函数则不行,这样做有点困难。
答案 1 :(得分:3)
它遵循另一种解决方案,即基于 sfinae 而非部分专业化的解决方案。
我试图提供一个最小的,完整的例子
我也在示例中介绍了完美转发,但它与问题中的那个非常不同,所以我决定让它更类似于那个。
#include<functional>
#include<type_traits>
template <class FunctionType> class Entry {
std::function<FunctionType> internalFunction;
template<typename R, typename... Args>
typename std::enable_if<std::is_void<R>::value>::type
invoke(Args... args) {
internalFunction(args...);
}
template<typename R, typename... Args>
typename std::enable_if<not std::is_void<R>::value, R>::type
invoke(Args... args) {
return internalFunction(args...);
}
public:
Entry(std::function<FunctionType> f)
: internalFunction{f} { }
template<class... Arguments>
auto operator()(Arguments... arguments) -> decltype(internalFunction(arguments...)){
return invoke<typename std::function<FunctionType>::result_type>(arguments...);
}
};
int f() { return 42; }
void g() { }
int main() {
Entry<int()> e1(&f);
e1();
Entry<void()> e2(&g);
e2();
}
有关 sfinae 的更多详情,请参阅here。