代码之家  ›  专栏  ›  技术社区  ›  Jonathan Mee

在专门化类时,如何获取不同数量的模板参数?

  •  1
  • Jonathan Mee  · 技术社区  · 6 年前

    我只是问了一个问题: Can I get the Owning Object of a Member Function Template Parameter? Yakk - Adam Nevraumont

    template<class T>
    struct get_memfun_class;
    
    template<class R, class T, class...Args>
    struct get_memfun_class<R(T::*)(Args...)> {
        using type=T;
    };
    

    这显然是一个最初的声明,然后是 struct get_memfun_class 专门化可以有不同数量的模板参数吗?

    template<typename T>
    void foo(const T&);
    
    template<typename K, typename V>
    void foo<pair<K, V>>(const pair<K, V>&);
    

    是否没有要求专门化必须采用相同数量的参数?

    2 回复  |  直到 6 年前
        1
  •  5
  •   Rakete1111    6 年前

    template<class T> // one argument
    struct get_memfun_class; // get_memfun_class takes one template (type) argument
    
    template<class R, class T, class...Args>
    struct get_memfun_class<R(T::*)(Args...)> {
    //                      ^^^^^^^^^^^^^^^^
    //                      one type argument
        using type=T;
    }; // explicit specialization takes one template argument
    

    是的,显式专门化有三个模板参数,但这并不意味着显式专门化需要三个参数。它们是可以推断出来的。您可以使用多个类型参数来形成一个类型,这就是正在发生的事情。还可以考虑完全专门化模板:

    template <>
    struct get_memfun_class<void>;
    //                      ^^^^
    //                    one type argument
    

    在这里也是一样的。是的,显式专门化不接受任何参数,但这只是意味着没有可以推导的参数,实际上您正在显式地编写一个模板参数( void

    您的示例无效,因为您不能部分专用化函数。

        2
  •  4
  •   max66    6 年前

    是否没有要求专门化必须采用相同数量的参数?

    当你写作的时候

    template<class T>
    struct get_memfun_class;
    

    你这么说 get_mumfun_class 是一个模板 struct typename 当你写作时

    template<class R, class T, class...Args>
    struct get_memfun_class<R(T::*)(Args...)> {
        using type=T;
    };
    

    您定义了一个专门化,该专门化接收表单中的单个模板typename参数 R(T::*)(Args...) .

    R(T::*)(参数…) ,可以推断出多个模板参数( R , T 以及变量 Args... R(T::*)(参数…)

    例如,这样的事情合法吗?

    template<typename T>
    void foo(const T&);
    
    template<typename K, typename V>
    void foo<pair<K, V>>(const pair<K, V>&);
    

    不,但是(如注释中所述)第二个不是类/结构部分专门化(其中 std::pair<K, V> 保持单一类型),这是合法的;它是一个模板 功能

    满的 专门化模板函数;因此它是合法的(通过示例)

     template<>
     void foo<std::pair<long, std::string>(const std::pair<long, std::string>&);
    

    正如法律所规定的那样 get_memfun_class

    template<>
    struct get_memfun_class<std::pair<long, std::string>> {
        using type=long long;
    };