创建可折叠模板参数包
Create foldable template parameter pack
问题
是否可以创建可折叠(※折叠表达式)模板参数包?
例
考虑以下示例(采用两个类型为int
(衰减)的参数的函数)。
template<
typename L,
typename R,
typename = std::enable_if_t<
std::is_same_v<int, std::decay_t<L>>
&& std::is_same_v<int, std::decay_t<R>>
>
>
int F(L Left, R Right){
return 0x70D0;
}
是否可以创建可以折叠的模板参数包,以避免多次编写相同的代码片段(即std::is_same_v
)?
下面表示std::pack
的东西可以简化使用SFINAE吗?
typename = std::enable_if_t<(... && std::is_same_v<int, std::decay_t<std::pack<L, R>>>)>
我尝试过什么
我试图使用T
包和别名单L
和R
来解决问题。 但是对于某些人来说,以下代码在 MSVC 15.9.4+28307.222 上编译和运行时没有错误(第二个F
函数调用的第二个参数,衰减,不等于int
):
template<
typename... T,
typename L = std::tuple_element_t<0, std::tuple<T...>>,
typename R = std::tuple_element_t<1, std::tuple<T...>>,
typename = std::enable_if_t<(... && std::is_same_v<int, std::decay_t<T>>)>
>
int F(L Left, R Right){
return 0x70D0;
}
int main(){
F(3, 5); // OK
F(3, "5"); // OK, but should not compile
}
PS 另外,我是否错过了上面的代码中使 SFINAE 正常工作的内容(仅具有int, int
(衰减)参数的过滤器函数)?
是否可以创建可以折叠的模板参数包以避免多次编写相同的代码片段?
到位?不是在第 17 C++。您必须将类型包装到某种template <typename...> struct typelist;
中,然后在其他地方解开它们。这需要一层间接。
据我所知,没有办法写出像std::pack
这样的东西。
我试图使用 T 包和混叠单个 L 和 R 来解决问题。
在您的代码中,T...
将始终为空,因为它不会被任何东西推导。L
和R
的默认模板参数值将被忽略,因为它们是由函数调用推导的。
你需要这样的东西:
template<
typename... T,
typename = std::enable_if_t<(... && std::is_same_v<int, T>)>
>
int F(T...){
return 0x70D0;
}
在 C++20 中,您应该能够按如下方式使用 lambda:
template<
typename L,
typename R,
typename = std::enable_if_t<[]<typename... Ts>(){
return (... && std::is_same_v<int, Ts>)
}.operator()<L, R>()>
>
int F(L Left, R Right){
return 0x70D0;
}
玩太晚了吗?
是否可以创建可以折叠的模板参数包,以避免多次编写相同的代码片段?
据我所知,不是F()
本身。
但是,您可以通过示例将这些类型重新打包到被调用函数的列表中。
我的意思是。。。如果你声明定义(仅声明:不需要定义它,因为仅在以下函数[编辑:按照Barry的建议(谢谢)定义函数简化使用]decltype()
中使用)
template <typename T, typename ... Ts>
constexpr auto isSameList ()
-> std::bool_constant<(... && std::is_same_v<T, std::decay_t<Ts>>)>
{ return {}; }
在可以使用模板折叠的地方,您可以 SFINAE 启用/禁用F()
,如下所示
template <typename L, typename R,
std::enable_if_t<isSameList<int, L, R>(), bool> = true>
int F(L Left, R Right)
{ return 0x70D0; }
以下是完整的编译示例
#include <type_traits>
template <typename T, typename ... Ts>
constexpr auto isSameList ()
-> std::bool_constant<(... && std::is_same_v<T, std::decay_t<Ts>>)>
{ return {}; }
template <typename L, typename R,
std::enable_if_t<isSameList<int, L, R>(), bool> = true>
int F(L Left, R Right)
{ return 0x70D0; }
int main ()
{
F(3, 5); // compile
//F(3, "5"); // compilation error
}
你几乎拥有它:
template <typename L,typename R,
typename = std::enable_if_t<std::is_same_v<std::tuple<int,L,R>,std::tuple<L,R,int>>>>
int F(L Left, R Right){
return 0x70D0;
}
int main(){
F(3, 5); // OK
F(3, "5"); // Does not compile
F("5", 3); // Does not compile
}
或可变参数版本:
template <typename... T,
typename = std::enable_if_t<std::is_same_v<std::tuple<int,T...>,std::tuple<T...,int>>>>
int F(T... args){
return 0x70D0;
}
int main(){
F(3, 5); // OK
F(3, "5"); // Does not compile
F("5", 3); // Does not compile
}
- 在C++中,使用带有 std::optional 参数的函数<T>来表示可选参数是否有意义?
- 如何使用要传递给 mt19937 的可选随机种子参数设计函数
- 如何在不知道C++中有多少可选参数的情况下在循环中使用va_arg?
- 如果可推导类型上有替换,可变参数模板类型推导会使编译器崩溃
- 为什么数组大小信息可用于"sizeof"运算符和 delete[] 运算符,但在将数组作为参数传递到
- C++ 带有默认参数的结构,可选择在构造函数中更改
- 是否可以在命令行中将输入参数传递给可执行文件
- 如何使用可选的随机种子参数创建 roll_die() 函数
- 通过跳过可选参数来填充参数包
- 将折叠表达式传递给可变参数模板
- 创建 OpenCV 非自由版本 v4.3 时出错,可折叠.cpp错误 C2039、2605
- QT 中的可折叠小部件
- 别名一个模板函数,该功能没有参数可更简洁
- C++17 可变参数模板折叠
- std :: iS_constructiblinsibles与参数可转换为参数的参数
- 创建可折叠模板参数包
- 如何将可折叠元素(Qmenu,Qcombobox)渲染到使用QT的位图缓冲液
- 仅当参数可将某个类型的符号解释时,如何启用函数
- 如何处理可选参数 + 可选返回值
- 如何使类模板参数可选