【问题标题】:Why non deductible template parameters is problematic?为什么不可扣除的模板参数有问题?
【发布时间】:2019-04-28 21:07:30
【问题描述】:

尝试编译这段代码会导致错误。

template <typename T>
struct MyClass;

template <typename T, std::size_t sz>
struct MyClass<T> {
    static void print() {
        std::cout << "Partially specialized" << std::endl;
    }
};

错误:模板参数在部分特化中不可推导出

尝试使推断sz 成为可能解决了这个问题。例如:

template <typename T, std::size_t sz>
struct MyClass<T[sz]> {
    static void print() {
        std::cout << "Partially specialized" << std::endl;
    }
};

我的问题是,编译器如何解释这样的程序以及不允许使用第一个结构的原因是什么?

进一步说明: 我在想,如果初始代码是可编译的,我们可以以如下方式使用它:MyClass&lt;int, 4&gt;::print()。

【问题讨论】:

    标签: c++11 templates c++14 metaprogramming


    【解决方案1】:

    我在想,如果初始代码是可编译的,我们可以以如下方式使用它:MyClass&lt;int, 4&gt;::print()。

    这不是模板专业化的工作方式。如果您将基本模板声明为template &lt;class T&gt; struct MyClass,那么MyClass 只能使用一个模板类型参数来实例化。不能实例化为MyClass&lt;int, int&gt; 或MyClass&lt;int, 3&gt; 或MyClass&lt;3&gt;。

    模板特化可以特化基本模板参数。

    回到你的问题。所以MyClass可以这样实例化:MyClass&lt;int&gt;、MyClass&lt;float&gt;、MyClass&lt;SomeClass&gt;、MyClass&lt;int*&gt;、MyClass&lt;int[10]&gt;等等。

    当你写作时

    template <typename T, std::size_t sz>
    struct MyClass<T[sz]> { 
    

    您将模板MyClass&lt;T&gt; 专门用于任何T,它是一个数组或任何大小的任何类型。例如MyClass&lt;int[24]&gt; 将使用此专业化。

    当你写作时

    template <typename T, std::size_t sz>
    struct MyClass<T> {
    //             ^
    //             no sz here
    

    这看起来像是 MyClass 的特化,但不是,因为 sz 没有出现在特化参数中。

    【讨论】:

      【解决方案2】:

      在 C++ 中,在我们声明一个模板之后,我们可以根据需要对其进行特化,例如:

      template <typename T> foo;
      template <typename U> foo<U*>;
      

      编译器现在期望指针类型有不同的定义。但是 - 专业化实际上需要专门化 - 它不能像原始声明那样通用。在您的情况下,您正在 添加 一个模板参数。这甚至与它的扣除无关——这不是你能做的。

      因此,如果您查看错误消息other compiles give you:

      (叮当声:)

      <source>:7:8: error: class template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list
      struct MyClass<T> {
             ^      ~~~
      <source>:6:1: error: too many template parameters in template redeclaration
      template <typename T, std::size_t sz>
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      

      (MSVC:)

      <source>(11): error C2753: 'MyClass<T>': partial specialization cannot match argument list for primary template
      <source>(11): error C2764: 'sz': template parameter not used or deducible in partial specialization 'MyClass<T>'
      

      你会在错误信息修辞中看到不同的焦点:你必须专攻,但你不是。

      另一方面,在您的第二个代码 sn-p 中,您正在专门化:现在您没有为所有类型 T 定义 MyClass,而只是为某个特定的数组定义元素的数量。你真的应该这样想:

      template <typename U, std::size_t sz>
      struct MyClass<U[sz]> {
          static void print() {
              std::cout << "Partially specialized" << std::endl;
          }
      };
      

      所以特化适用于T 的形式为U[sz]。

      【讨论】:

      • 感谢您的回复。你能详细说明你的第一句话吗?特别是,你是什么意思它没有意义?第二段代码 sn -p 编译良好,运行良好。
      • 感谢您的编辑。考虑到第二个代码 sn-p,我们可以添加第二个模板参数。所以,您能否详细说明一下您的陈述:“在您的情况下,您正在添加一个模板参数。这甚至不是关于它的推导 - 这不是您可以做的事情。”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多