为什么非扣除模板参数有问题?

Why non deductible template parameters is problematic?

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

template <typename T>
struct MyClass;

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

error: template parameters not deducible in partial specialization

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

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

我的问题是,编译器如何解释这样的程序以及不允许具有第一个结构背后的合理性是什么?

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

在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>'

您会在错误消息修辞中看到不同的重点:您必须专精,但您不是。

另一方面,在您的第二个代码片段中,您 专业化:现在您没有为所有类型 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].

I am thinking that if the inital code was compilable, we could use it in a manner such as: MyClass<int, 4>::print().

这不是模板专业化的工作方式。如果将基本模板声明为 template <class T> struct MyClass,则 MyClass 只能用一个模板类型参数实例化。它不能实例化为 MyClass<int, int>MyClass<int, 3>MyClass<3>.

模板特化只能特化基本模板参数。

回到你的问题。所以 MyClass 可以像这样实例化:MyClass<int>MyClass<float>MyClass<SomeClass>MyClass<int*>MyClass<int[10]> 等等。

写的时候

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

您将模板 MyClass<T> 专门化为任何 T 数组或任何大小的任何类型。例如 MyClass<int[24]> 将使用此专业。

当你写

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

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