【问题标题】:Variadic template partial specialization of a class to restrict type of template arguments类的可变参数模板部分特化以限制模板参数的类型
【发布时间】:2017-07-16 16:24:24
【问题描述】:

我有一个类Foo,它需要有可变数量的模板参数,但这些参数需要是某种通用类型,而不是完全任意的。例如

template < int I, typename T> struct Arg;
using type1 = Foo<Arg<3, double>>;
using type2 = Foo<Arg<1, int>, Arg<7, float>, Arg<1, int>>;

我想知道实现这一目标的最佳方法是什么。我想我需要先从一个普通的可变参数模板开始

template < typename ...T >
class Foo;

从那里,我可以沿着递归的道路前进

template < int I, typename T, typename ...Others>
template Foo<Arg<I, T>, Others...>
{
    ...
};

但是阅读this answer 到另一个问题让我想知道我对可变参数模板的了解以及有时如何避免递归。

我的问题是,模板参数预计采用相对严格的格式这一事实是否能够实现Foo 的部分特化,它不会是递归的,并且可以有效地处理所有Foos 形式Foo&lt;Arg&lt;...&gt;,Arg&lt;...&gt;,...&gt;?

【问题讨论】:

    标签: c++ variadic-templates


    【解决方案1】:

    这行得通:

    #include <iostream>
    
    template <int i, typename T> struct Arg;
    
    template <typename ...T>
    class Foo;
    
    template <int ...Is, typename ...Ts>
    class Foo<Arg<Is, Ts>...>
    {
    public:
        static constexpr unsigned int N = sizeof...(Is);
    };
    
    int main()
    {
        using type2 = Foo<Arg<1, int>, Arg<7, float>, Arg<1, int>>;
        std::cout << type2::N << "\n";
    }
    

    虽然在那种形式中使用模板参数可能会也可能不会容易或不方便,这取决于你想用它们做什么。

    【讨论】:

    • 仍然可以将参数放在元组中并在需要时访问它们,所以我不会说它们很难使用。只需添加 N 并键入 Arg 即可导出它们。
    【解决方案2】:

    您可以使用 SFINAE 做到这一点。这是一个草图:

    template<class...Bs>
    constexpr bool is_all_true(Bs...); // write this
    
    template<class T>
    constexpr bool is_valid_arg(); // write this
    
    template < class=void, class...Ts >
    class FooImpl;
    
    template < class...Ts >
    class FooImpl<std::enable_if_t<is_all_true( is_valid_arg<Ts>()...) >, Ts...> {
      // code
    };
    
    template<class...Ts>
    class Foo:FooImpl<void, Ts...> {};
    

    现在FooFooImpl,用于测试您的先决条件是否全部满足。

    你必须写is_all_trueis_valid_arg,其中is_valid_arg测试T是否是Arg&lt;int, Type&gt;的形式。

    例如,在 C++17 中,is_all_true 只是 return (true &amp;&amp; ... &amp;&amp; bs);(如果我没记错的话,true 是多余的,但为了清楚起见,我喜欢它)。在 C++11/14 中会更难。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-14
      • 1970-01-01
      • 2013-09-11
      相关资源
      最近更新 更多