首页 > 解决方案 > 创建可折叠模板参数包

问题描述

问题

是否可以创建可折叠(※折叠表达式)模板参数包

例子

考虑下面的例子(接受两个类型参数的函数intdecayed))。

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

我试过的

我尝试使用Tpack 和 aliasing single Land来解决这个问题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仅具有(衰减)参数的过滤函数)?

标签: c++c++17variadic-templatestemplate-meta-programmingsfinae

解决方案


是否可以创建可以折叠的模板参数包以避免多次编写相同的代码片段?

到位?不在 C++17 中。您必须将您的类型包装成某种类型,template <typename...> struct typelist;然后在其他地方解开它们。这需要一层间接。

std::pack据我所知,没有办法写出类似的东西。


我尝试使用 T 包和别名单个 L 和 R 来解决问题。 [...]

在您的代码中,T...它将始终为空,因为它没有被任何东西推断出来。LR的默认模板参数值被忽略,因为它们是由函数调用推导出来的。

你需要类似的东西:

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

推荐阅读