【问题标题】:When specializing a class, how can I take a different number of template parameters?专业化一个类时,如何获取不同数量的模板参数?
【发布时间】:2018-09-13 16:33:42
【问题描述】:

我刚刚问了这个问题: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 个专业化" 呃,只有一个专业化。
  • 我不明白这个问题。不同数量的模板参数是什么意思?该示例的模板参数数量(RTArgs)与主参数(T)的数量不同。此外,foo 示例也不合法,因为您不能部分专门化函数模板。
  • @Barry 第二个不是合法的,因为它是重载,而不是部分专业化?
  • @NathanOliver 作为重载是合法的,是的,但它被写成部分特化。
  • 啊,是的,错过了那部分。

标签: c++ templates language-lawyer variadic-templates template-specialization


【解决方案1】:

您似乎混淆了显式特化的模板参数和用于特化模板的模板参数。

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】:

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

    有;并且对您的示例感到满意。

    当你写作时

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

    您定义了一个特殊化,它以R(T::*)(Args...) 的形式接收单个模板类型名参数。

    从单一类型R(T::*)(Args...),您可以推断出更多的模板参数(RT 和可变参数Args...,在此示例中)但类型R(T::*)(Args...)(类的方法接收可变参数列表)保持为一个。

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

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

    不,但是(如 cmets 中所写)第二个不是类/结构部分特化(其中 std::pair&lt;K, V&gt; 保持单一类型),这是合法的;这是一个模板 function 被禁止的部分特化。

    但是你可以完全专门化一个模板函数;所以这是合法的(通过示例)

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

    【讨论】:

    • 第一句(“Yes;...”)似乎与您稍后写的相矛盾:“接收单个模板类型名争论的专业化”
    • @user463035818 - 你是对的:“是”作为对以“有没有”开头的问题的回答不是一个好主意;谢谢。用“有”修饰。
    猜你喜欢
    • 2017-09-10
    • 2022-10-15
    • 2016-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多