【发布时间】:2017-03-10 18:31:45
【问题描述】:
我有一个模板类,它必须在调用参数和返回类型都是泛型的函数之前执行一些操作。
这是方法:
template <typename ReturnType, typename ...Args>
ReturnType function (Args ...args) {
// prepare for call
// ...
ReturnType rv = makeCall(args...); // [1]
// dismiss the call
// ...
return rv;
}
当ReturnType 不是void 时,它当然可以正确编译。
当我在这种情况下使用它时:
function<void>(firstArg, secondArg);
编译器响应
error: return-statement with a value, in function returning 'void' [-fpermissive]
指向标有 [1] 的行。
除了将-fpermissive 传递给编译器之外,还有其他解决方案吗?
我希望有一个独特的方法,因为我发现可能的解决方案是使用enable_if 和is_same 实例化不同的版本。
提前谢谢你。
-- 更新--
这是一个完整的例子。我应该说我们的函数确实是类方法。
#include <type_traits>
#include <iostream>
class Caller {
public:
Caller() {}
template <typename ReturnType, typename ...Arguments>
ReturnType call(Arguments ... args) {
prepare();
ReturnType rv = callImpl<ReturnType>(args...);
done();
return rv;
}
private:
void prepare() {
std::cout << "Prepare\n";
}
void done() {
std::cout << "Done\n";
}
template <typename ReturnType, typename ...Arguments>
typename std::enable_if<std::is_same<ReturnType, void>::value, ReturnType>::type callImpl ( Arguments ... args) {
std::cout << "Calling with void\n";
return;
}
template <typename ReturnType, typename ...Arguments>
typename std::enable_if<std::is_same<ReturnType, bool>::value, ReturnType>::type callImpl (Arguments ... args) {
std::cout << "Calling with bool\n";
return true;
}
template <typename ReturnType, typename ...Arguments>
typename std::enable_if<std::is_same<ReturnType, int>::value, ReturnType>::type callImpl (Arguments ... args) {
std::cout << "Calling with int\n";
return 42;
}
};
int main(int argc, char *argv[]) {
Caller c;
auto rbool = c.call<bool> (1,20);
std::cout << "Return: " << rbool << "\n";
auto rint = c.call<int> (1,20);
std::cout << "Return: " << rint << "\n";
// the next line fails compilation. compile with --std=c++11
c.call<void>("abababa");
return 0;
}
-- 更新--
不是什么大问题:使用std::bind(&Caller::callImpl<ReturnType>, this, args)。
【问题讨论】:
-
你试过
function<void*>吗? -
在 C++17 中,您可能会使用
constexpr if (std::is_same<ReturnType,void>::value) { return; } else { return rv; }(好吧,这不是整个解决方案,因为您也不应该尝试实例化void rv,但您会发现偏差)。 -
谢谢@Someprogrammerdude,这是我想避免的,但目前这是最好的解决方案
-
谢谢@einpoklum,我知道这个解决方案,但它不可行,因为我的上下文不支持 c++17。还是谢谢你。
-
部分特化是错误的,我真的不知道我在想什么,但不可能部分特化函数。重载和使用例如
enable_if或其他一些类型特征可能是一个可能的解决方案。
标签: c++ c++11 templates variadic