Hap*_*tus 5 c++ templates variadic c++11
我有一个模板类,必须在调用参数和返回类型为泛型的函数之前执行某些操作.
这是方法:
template <typename ReturnType, typename ...Args>
ReturnType function (Args ...args) {
// prepare for call
// ...
ReturnType rv = makeCall(args...); // [1]
// dismiss the call
// ...
return rv;
}
Run Code Online (Sandbox Code Playgroud)
当然,如果ReturnType
没有正确编译它void
.当我在这种情况下使用它时:
function<void>(firstArg, secondArg);
Run Code Online (Sandbox Code Playgroud)
编译器响应
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;
}
Run Code Online (Sandbox Code Playgroud)
- 更新 -
不是一个大问题:使用std::bind(&Caller::callImpl<ReturnType>, this, args)
.
以下是我可以轻松重用的符合C++ 11标准的通用解决方案.
让我们从创建一个转换为空结构的简单类型特征开始void
.这不会引入任何代码重复.
struct nothing { };
template <typename T>
struct void_to_nothing
{
using type = T;
};
template <>
struct void_to_nothing<void>
{
using type = nothing;
};
template <typename T>
using void_to_nothing_t = typename void_to_nothing<T>::type;
Run Code Online (Sandbox Code Playgroud)
我们还需要一种方法来调用将最终void
返回类型转换为的任意函数nothing
:
template <typename TReturn>
struct helper
{
template <typename TF, typename... Ts>
TReturn operator()(TF&& f, Ts&&... xs) const
{
return std::forward<TF>(f)(std::forward<Ts>(xs)...);
}
};
template <>
struct helper<void>
{
template <typename TF, typename... Ts>
nothing operator()(TF&& f, Ts&&... xs) const
{
std::forward<TF>(f)(std::forward<Ts>(xs)...);
return nothing{};
}
};
template <typename TF, typename... Ts>
auto with_void_to_nothing(TF&& f, Ts&&... xs)
-> void_to_nothing_t<
decltype(std::forward<TF>(f)(std::forward<Ts>(xs)...))>
{
using return_type =
decltype(std::forward<TF>(f)(std::forward<Ts>(xs)...));
return helper<return_type>{}(std::forward<TF>(f), std::forward<Ts>(xs)...);
}
Run Code Online (Sandbox Code Playgroud)
用法:
template <typename ReturnType, typename ...Args>
void_to_nothing_t<ReturnType> function (Args ...args) {
// prepare for call
// ...
auto rv = with_void_to_nothing(makeCall, args...); // [1]
// dismiss the call
// ...
return rv;
}
Run Code Online (Sandbox Code Playgroud)
Matt Calabrese提出了一项名为"Regular Void"的提案,可以解决这个问题.你可以在这里找到它:"P0146R1".
取决于您希望在线条中完成的任务
// dismiss the call
Run Code Online (Sandbox Code Playgroud)
你可以使用:
template <typename ReturnType, typename ...Args>
ReturnType function (Args ...args) {
// prepare for call
// ...
CallDismisser c;
return makeCall(args...); // [1]
}
Run Code Online (Sandbox Code Playgroud)
只要析构函数CallDismisser
可以执行您需要执行的所有操作,这将起作用.
归档时间: |
|
查看次数: |
760 次 |
最近记录: |