C++ 作用域中的模板变量或模板类型定义
为什么不能在作用域内声明模板变量或模板typedef 我想用c++17编写这样的代码C++ 作用域中的模板变量或模板类型定义,c++,templates,c++17,C++,Templates,C++17,为什么不能在作用域内声明模板变量或模板typedef 我想用c++17编写这样的代码 auto foo = [](auto fun, auto... x) { template <typename T> using ReturnType = std::invoke_result_t<fun, T>; if constexpr (!(std::is_same_v<void, ReturnType<decltype(x)>> || ...
auto foo = [](auto fun, auto... x) {
template <typename T>
using ReturnType = std::invoke_result_t<fun, T>;
if constexpr (!(std::is_same_v<void, ReturnType<decltype(x)>> || ... ||
false)) {
return std::tuple<ReturnType<decltype(x)>...>(fun(x)...);
} else {
(fun(x), ...);
return;
}
};
然后在函数中使用
ReturnType<decltype(fun),delctype(x)>
ReturnType
它越来越长,我必须将每个本地类型作为模板参数。代码实际上更简单,没有引入任何帮助程序:
if constexpr ((!std::is_void_v<decltype(fun(x))> && ...)) {
return std::tuple(fun(x)...);
} else {
(fun(x), ...);
}
没多久了
这就是说,我发现这个构造并没有太大的帮助,因为对于
void
和非void
的情况,你会得到非常不同的结果。也许f(x)
仍然是x
但是f(y)
是void
,我们会得到foo(x,x)
是tuple
但是foo(x,y)
是void
?很难编码
我建议不要放弃所有的退货类型,而要解决坏的退货类型。例如:
struct Void { };
template <typename F, typename... Args,
typename R = std::invoke_result_t<F, Args...>,
REQUIRES(std::is_void_v<R>)>
Void invoke_void(F&& f, Args&&... args) {
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
return Void{};
}
template <typename F, typename... Args,
typename R = std::invoke_result_t<F, Args...>,
REQUIRES(!std::is_void_v<R>)>
R invoke_void(F&& f, Args&&... args) {
return std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}
using F = decltype(fun);
if constexpr ((!std::is_void_v<std::invoke_result_t<F, decltype(x))> && ...)) {
return std::tuple(std::invoke(fun, x)...);
} else {
(fun(x), ...);
}
struct Void { };
template <typename F, typename... Args,
typename R = std::invoke_result_t<F, Args...>,
REQUIRES(std::is_void_v<R>)>
Void invoke_void(F&& f, Args&&... args) {
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
return Void{};
}
template <typename F, typename... Args,
typename R = std::invoke_result_t<F, Args...>,
REQUIRES(!std::is_void_v<R>)>
R invoke_void(F&& f, Args&&... args) {
return std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}
auto foo = [](auto fun, auto... x) {
return std::tuple(invoke_void(fun, x)...);
};