作用域中的模板变量或模板类型定义
Template variable or template typedef in a scope
为什么模板变量或模板类型定义不能在作用域内声明?
我想用 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)>> || ... ||
false)) {
return std::tuple<ReturnType<decltype(x)>...>(fun(x)...);
} else {
(fun(x), ...);
return;
}
};
此代码定义了一个函数foo
该函数x...
fun
和一堆参数。如果未void
所有返回类型fun(x)
则返回结果元组。如果至少void
一种返回类型,则只需调用所有函数,但返回void
。
在这个简单的示例中,我当然可以用decltype(fun(x))
替换ReturnType<decltype(x)>
,但在我的用例中,实际类型要复杂得多,上面的代码仅作为动机。
另外,我讨厌写ReturnType<decltype(x)>
.我更喜欢写ReturnType(x)
,但这可能是不可能的。
我不喜欢的解决方案:将函数外部的模板类型定义
为template<typename Fun, typename T>
using ReturnType = std::invoke_result_t<Fun,T>;
然后在函数中使用
ReturnType<decltype(fun),delctype(x)>
这越来越长,我必须将每个本地类型作为模板参数。
代码实际上更简单,没有引入任何帮助程序:
if constexpr ((!std::is_void_v<decltype(fun(x))> && ...)) {
return std::tuple(fun(x)...);
} else {
(fun(x), ...);
}
&&
和 ||
具有空包的默认值(分别为 true
和 false
(,因此您不必将它们转换为一元运算符。而且您不需要invoke_result_t
,因为您只是直接拨打电话。即使你这样做了:
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), ...);
}
不多了。
<小时 />也就是说,我发现这种结构不是很有帮助 - 因为对于void
和非void
情况,你会得到截然不同的结果。也许f(x)
仍然是一个X
但f(y)
void
,我们会得到foo(x,x)
tuple<X,X>
但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)...);
}
现在,我们总是可以调用函数并返回它:
auto foo = [](auto fun, auto... x) {
return std::tuple(invoke_void(fun, x)...);
};
相关文章:
- 有没有一种方法可以通过"typedef"为重新定义的基本类型定义特征和强制转换运算符
- 强枚举类型定义:Clang Bug 还是 C++11 标准不确定性?
- 列表参数的类型定义
- 使用模板化的键类型定义 std::map,该键类型基于作为参数接收的函数
- 关于 C++ 中的函数类型定义
- C++(和 ROS) - 包含与前向声明引用,设置默认值和类型定义
- 将使用/类型定义限制为类范围
- 模板类型定义?
- C++:模板类的类型定义
- 如何对命名空间限定类型进行类型定义?
- 此递归模板类型定义是否有效C++?
- 具有调整对齐方式的类型定义
- C++从抽象类型定义类成员
- 用于C++代码的 API 监视器类型定义 (XML)
- 如何将result_of与函数类型定义一起使用
- 在C++的适当类型定义位置
- 如何根据模板类型定义浮点常量?
- 如何为缺少预定义运算符而不扩展命名空间"std"的标准类型定义运算符>> (istream &, ...)?
- 参数化类的别名(或类型定义)内部类
- 如果我想从类型"T"定义元素的容器(来自 STL),那么"T"必须使用默认构造函数?