Matching variadic non-type templates

后端 未结 3 1904
予麋鹿
予麋鹿 2021-02-18 14:13

Let\'s say I have two structs, Foo and Bar:

template
struct Foo{};

template
struct Bar{};
         


        
3条回答
  •  被撕碎了的回忆
    2021-02-18 14:29

    In C++14, you could not deduce T in:

    template class S, T... U, T... V>
    struct match_class, S> : std::true_type{};
    

    but in C++17, you can. The behavior you see is correct.

    In C++14, since you cannot deduce T, you need a way of explicitly providing it. So you might require the class templates themselves to indicate their non-type template parameter type:

    template  struct Foo { using type = int; };
    template  struct Bar { using type = unsigned long; };
    

    Or have an external trait for this. And then explicitly write out everything - two class templates match if they have the same non-type template parameter and then also have the same class template, in that order:

    template  struct make_void { using type = void; };
    template  using void_t = typename make_void::type;
    
    template 
    struct match_class_impl : std::false_type { };
    
    template  class S, T... U, T... V>
    struct match_class_impl, S> : std::true_type{};
    
    template 
    struct match_class : std::false_type { };
    
    template 
    struct match_class>
        : match_class_impl
    { };
    

    This is a consequence of adding support for template auto. In C++14, [temp.deduct.type] contained:

    A template type argument cannot be deduced from the type of a non-type template-argument. [Example:

    template void f(double a[10][i]);
    int v[10][20];
    f(v); // error: argument for template-parameter T cannot be deduced
    

    -end example]

    But in C++17, it now reads:

    When the value of the argument corresponding to a non-type template parameter P that is declared with a dependent type is deduced from an expression, the template parameters in the type of P are deduced from the type of the value. [ Example:

    template struct A { };
    
    template struct C;
    template struct C> {
      using Q = T;
    };
    
    using R = long;
    using R = C>::Q;           // OK; T was deduced to long from the
                                    // template argument value in the type A<2>
    

    — end example ] The type of N in the type T[N] is std​::​size_­t. [ Example:

    template struct S;
    template struct S {
      using Q = T;
    };
    
    using V = decltype(sizeof 0);
    using V = S::Q;        // OK; T was deduced to std​::​size_­t from the type int[42]
    

    — end example ]

提交回复
热议问题