不了解 C++ 模板专业化和常量

Not understanding C++ Template Specialization And Constants

我正在努力思考模板特化,但我有点困惑(可能不理解 typename 实际上是什么,或者编译器期望什么)

示例 1(编译):

template <typename A, typename... Args>
class Example
{
public:
    Example(){}
    virtual ~Example(){}
};

template <typename A, typename... Args>
class Example<A, int, Args...>{
    Example(){}
    virtual ~Example(){}
};

示例 2(编译):

template <typename A, int, typename... Args>
class Example
{
public:
    Example(){}
    virtual ~Example(){}
};

template <typename A, typename... Args>
class Example<A, 2, Args...>{
    Example(){}
    virtual ~Example(){}
};

示例 3(失败):

template <typename A, typename... Args>
class Example
{
public:
    Example(){}
    virtual ~Example(){}
};

template <typename A, typename... Args>
class Example<A, 2, Args...>{
    Example(){}
    virtual ~Example(){}
};

错误是:

错误:type/value ‘template class Example

的模板参数列表中的参数 2 不匹配

问题:

首先,我是泛型编程的新手,希望我问的是正确的问题。编译器规范术语对我来说还是有点陌生​​。

谢谢

EDIT/Solution:

在我了解发生了什么之后(根据 Yakk 的解释),这是我最终的解决方案。我在某处读到一位 C++ 大师的 "You can solve any problem by adding another layer of abstraction"。现在我知道那是什么意思了 :D

 enum ETypes
{
    UNKNOWN = 0,
    INT = 1,
    FLOAT = 2,
    STRING = 3,
    FUNC = 4,
};

// This is to use the ETypes as a type.
// Note that T is not a type, hence use it as RHS
template<ETypes T>
class ETypeName
{
public:
    ETypes type = T;
};


// The example
template <typename A, typename... Args>
class Example
{
private:
    Example();              // Hide the constructor as private
                            // to generate compilation error
    virtual ~Example(){}
};


// LOOK! We can use the Enum to specialize the class.
template <>
class Example<ETypeName<ETypes::INT>>{
public:
    ETypes mType;
    Example():mType(ETypes::INT){}
    virtual ~Example(){}
};

并且在 main() 中:

    Example<ETypeName<ETypes::INT>> x;

    // This can't happen. Private constructor. Not specialized yet
//  Example<ETypeName<ETypes::FLOAT>> x1;

What is happening? Is the compiler trying to treat the constant as typename?

是的。

If typename can be specialized as int, and int can be specialized as 2, why can't a typename be specialized as 2?

typename 开头的模板参数需要一个类型作为参数。在您的第二个示例中,第二个模板参数是 int,而不是 typename something。因此,它不期望类型作为参数,而是实际的 int 值。

你的第三个例子使用了一个只需要 typename 模板参数的模板定义,但是你尝试给它一个 int 值作为参数。这就是您收到错误的原因。

What would be a "proper" method to specialize the class with int or enum?

不确定我是否正确理解问题的含义。使用 int 第二个模板参数为实例专门化模板的正确方法是第二个模板定义。

初级专业看起来像这样:

template <typename A, typename... Args>
class Example

当您键入 Example<stuff goes here> 时,它 始终 与主要专业化的 <typename A, typename... Args> 参数列表相匹配。

这是一个完全不同的野兽:

template <typename A, typename... Args>
class Example<A, int, Args...>

这是一个二级专业。这里,

template <typename A, typename... Args>

不是论证表,而是推论表。

参数列表是:

class Example<A, int, Args...>

在这里。 <> 之间的内容仅用于 模式匹配 与传递给主要专业化的参数。

类型和non-type模板参数是不同的东西。主要专业详细说明了哪些参数是类型,哪些参数是 non-type.

一旦它们与主要匹配,每个次要特化都会与参数进行模式匹配。每个可行的候选人都会被检查,并使用一个相当复杂的系统来确定哪个是 "more specialized",我不会在这里讨论其规则。