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

时间:2017-02-07 00:13:42

标签: c++11 templates specialization variadic

我试图围绕模板专业化,我有点困惑(也许不了解实际上是什么类型名称,或编译器期望的)

示例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(){}
};

错误是:

错误:模板参数列表中参数2的类型/值不匹配'模板类示例

问题:

首先,我是通用编程的新手,我希望我能提出正确的问题。编译器规范术语对我来说仍然有点陌生。

  • 发生了什么事?编译器是否试图将常量视为 TYPENAME?
  • 如果typename可以专门用作int,并且int可以专用为2,为什么typename不能专门用作2?
  • 用int或enum专门化类的“正确”方法是什么?
  • 我问的是正确的问题吗?

谢谢

修改/解决方案:

在我理解了正在发生的事情之后(来自Yakk的解释),这是我的最终解决方案的样子。我在C ++大师之一的某处读过“你可以通过添加另一层抽象来解决任何问题”。现在我知道这意味着什么: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;

2 个答案:

答案 0 :(得分:3)

主要专业化如下:

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...>

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

类型和非类型模板参数是不同的东西。主要特化详细说明了哪些参数是类型,哪些参数是非类型。

一旦他们与主要匹配,每个次要专业化都与参数进行模式匹配。检查每个可行的候选人,并使用一个相当复杂的系统来确定哪个是“更专业化”,我不会在这里遵守规则。

答案 1 :(得分:2)

  

发生了什么事?编译器是否试图将常量视为typename?

  

如果typename可以专门用作int,并且int可以专门用作2,为什么typename可以专门用作2?

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

您的第三个示例使用的模板定义仅需要typename模板参数,但您尝试将int值作为参数。这就是你得到错误的原因。

  

什么是&#34;适当的&#34;用int或enum专门化类的方法?

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