【问题标题】:C++ variadic number of variadic template parameters可变参数模板参数的 C++ 可变参数数量
【发布时间】:2017-08-04 22:45:32
【问题描述】:

拥有一个可变参数模板很简单,我可以对其进行专门化,所以它只接受一个TStringConstant,它是一些chars 中的一个string_constant

template <typename TStringConstant, typename TValue>
class entry;

template <char... key, typename TValue>
class entry<string_constant<key...>, TValue>{}

如果我想创建一个模板类,它可以接受不同chars 的可变数字TStringConstants,有没有办法做到这一点?也许带有模板模板参数?

所以以下所有内容都是有效的:

entry_list<string_constant<'c','b','a'>, string_constant<'d','e','f','g'>>();
entry_list<string_constant<'c','b','a'>, string_constant<'d','e','f','g'>, string_constant<'d','e','z','z'>>();
entry_list<string_constant<'a','b','c'>>();

如果它会拒绝 entry_list&lt;something_else&lt;'c','b','a'&gt;&gt; 就像 entry&lt;something_else&lt;'c','b','a'&gt;, bool&gt; 将无法编译一样。

【问题讨论】:

    标签: c++ c++11 templates variadic-templates template-specialization


    【解决方案1】:

    您可以使用static_assert 来完成。我不知道如何以一种对 sfinae 友好的方式实现它,但我猜你并不关心这个。

    就这样吧:

    template <class... Args> struct entry {
        static_assert(are_string_constant<Args...>::value, "invalid template args for entry");
    };
    
    auto test()
    {
      entry<string_constant<'c', 'd'>> e1; // OK
      entry<string_constant<'c', 'd'>, string_constant<'a', 'b', 'c', 'd'>> e2; // OK
    
      // entry<int,
      //       string_constant<'c', 'd'>,
      //       string_constant<'a', 'b', 'c', 'd'>> e3; // static_assert kicks in
    
      // entry<definitely_not_string_constant<'c', 'd'>,
      //       string_constant<'a', 'b', 'c', 'd'>> e4; // static_assert kicks in
    
    
    }
    

    are_string_constant 的构建非常简单:

    template <char... Args> struct string_constant {};
    template <char... Args> struct definitely_not_string_constant {};
    
    // --- is_string_constant -----
    
    template <class T> struct is_string_constant : std::false_type {};
    
    template <char... Args>
    struct is_string_constant<string_constant<Args...>> : std::true_type {};
    
    // --- are_string_constant -----    
    
    template <class... Args> struct are_string_constant;
    
    template <class A0, class... Args>
    struct are_string_constant<A0, Args...>
         : std::integral_constant<bool, (is_string_constant<A0>::value &&
                                         are_string_constant<Args...>::value)>::type
    {};
    
    template <class T> struct are_string_constant<T> : is_string_constant<T>::type {};
    

    在 c++17 中,使用fold expressions 更容易实现(因为您不需要are_string_constant):

    template <class... Args>
    struct entry {
        static_assert((... && is_string_constant<Args>::value),
                      "invalid template args for entry");
    };
    

    【讨论】:

      【解决方案2】:

      我看到的真正问题是:你想如何使用你的 entry_list 类的可变参数列表?

      我喜欢 bolov 的解决方案 (+1),但是,如果您接受递归解决方案,我建议使用继承。

      以下是一个完整的例子

      template <char ...>
      struct string_constant
       { };
      
      template <char ...>
      struct something_else
       { };
      
      template <typename ...>
      class entry_list;
      
      template <>
      class entry_list<>
       { };
      
      template <char ... keys, typename ... Scs>
      class entry_list<string_constant<keys ...>, Scs ...>
         : public entry_list<Scs ...>
       { };
      
      int main ()
       {
         entry_list<string_constant<'c','b','a'>,
                    string_constant<'d','e','f','g'>>(); // compile
      
         entry_list<string_constant<'c','b','a'>,
                    string_constant<'d','e','f','g'>,
                    string_constant<'d','e','z','z'>>(); // compile
      
         entry_list<string_constant<'a','b','c'>>(); // compile
      
         //entry_list<something_else<'c','b','a'>>(); // compilation error
      
         //entry_list<string_constant<'c','b','a'>, bool>(); // compilation error
       }
      

      如果不想使用继承,可以改用static_assert(),如下

      template <char ... keys, typename ... Scs>
      class entry_list<string_constant<keys ...>, Scs ...>
       { static_assert(sizeof(entry_list<Scs...>), "!"); };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-14
        相关资源
        最近更新 更多