gpt4 book ai didi

c++ - 在 C++11 的模板化函数中处理 void 变量

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:56:04 24 4
gpt4 key购买 nike

我有一个模板类,它必须在调用一个参数和返回类型都是通用的函数之前执行一些操作。

这是方法:

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) .

最佳答案

这是我对通用的 C++11 兼容解决方案的尝试,您可以轻松地重复使用它。

让我们从创建一个简单的 type trait 开始,它将 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;

我们还需要一种方法来调用任意函数来转换最终的 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)...);
}

用法:

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;
}

live wandbox example


Matt Calabrese 提出了一个名为“Regular Void” 的提案,可以解决这个问题。 You can find it here: "P0146R1" .

关于c++ - 在 C++11 的模板化函数中处理 void 变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42725427/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com