【问题标题】:Template specialization with non-empty template parameter list具有非空模板参数列表的模板特化
【发布时间】:2016-10-18 14:26:54
【问题描述】:

我很难理解下面的代码

template <typename T>
struct function_traits
    : public function_traits<decltype(&T::operator())>
{};
// For generic types, directly use the result of the signature of its 'operator()'

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
// we specialize for pointers to member function
{
  // ...
}

int main()
{
    auto lambda = [](int i) { return long(i*10); };

    typedef function_traits<decltype(lambda)> traits;

    // ...

    return 0;
}

出现在答案https://stackoverflow.com/a/7943765/7006673

这里,

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>

似乎表明模板类的特殊化

template <typename T>
struct function_traits

然而,特化template &lt;typename ClassType, typename ReturnType, typename... Args&gt; 的模板参数列表不为空(即不等于template &lt;&gt;)。 谁能帮我理解一下,这是什么特化,模板参数ClassTypeReturnTypeArgs是怎么推导出来的?

非常感谢。

【问题讨论】:

    标签: c++ templates c++14 template-specialization type-deduction


    【解决方案1】:

    这是什么专业?

    这是partial specializationtype_traits 显式实例化为:

    T = ReturnType(ClassType::*)(Args...) const
    

    但是这个T 依赖于ReturnTypeClassTypeArgs。这就是为什么声明中没有template &lt;&gt;(即full specialization),而是带有描述特定类型T 的新参数的模板声明。

    模板参数ClassType、ReturnType、Args是如何推导出来的?

    它们是在模板用适合这种特化的表达式实例化时推导出来的。在这里,ReturnType(ClassType::*)(Args...) const 只能替换为指向方法的指针。

    这是SFINAE 的示例。

    【讨论】:

    • 非常感谢。还有一个问题:我认为类型推导只能用于函数的模板参数,而不能用于结构和类的模板参数——我错了吗?
    • 只能对函数的模板参数进行隐式实例化:在调用函数时显式传递参数,因此可以隐式推断出它们的类型。这里function_traits&lt;decltype(lambda)&gt;T=decltype(lambda) 的显式实例化
    • 谢谢!而ReturnTypeClassTypeArgs可以在decltype(lambda)的基础上进行推演,因为decltype(lambda)是模板参数——是吗?
    【解决方案2】:

    这是部分专业化。它不能是像 typename T 这样的“任何东西”,但它仍然有一些可变性,所以它不是一个完整的专业化。

    此外,您要匹配的内容是原始结构/类模板行中的类型数量以及专业化名称后面的&lt;...&gt;。这有点奇怪,因为它是不对称的。

    在你的部分专业化中:

    struct function_traits<ReturnType(ClassType::*)(Args...) const>
    

    所有三个模板化类型组合起来仍然只创建一个类型 - 一个指向成员函数的指针。这与“父”模板化类型的类型数量相同,即使该单一类型在专业化中被分解为 3 个额外的模板化类型。

    // this is what I'm calling the "master template", this isn't an official term
    template<class A, class B, ......., class N>
    class Foo{};
    
    template</*...This can have as many (or 0) entries as you need for this specialization...*/>
    class Foo</*...This must have the same number as master template above, but can be broken down into as many smaller pieces as you want...*/> {};
    

    【讨论】:

      猜你喜欢
      • 2018-06-25
      • 2011-07-26
      • 2014-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多