【问题标题】:Not understanding C++ Template Specialization And Constants不了解 C++ 模板专业化和常量
【发布时间】:2017-06-24 02:12:02
【问题描述】:

我正试图围绕模板专业化,我有点困惑(也许不理解 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(){}
};

错误是:

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

问题:

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

  • 发生了什么?编译器是否试图将常量视为 类型名称?
  • 如果 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 被视为非类型参数,但模板类需要一个类型。
  • 啊,这是我错过的东西

标签: c++11 templates specialization variadic


【解决方案1】:

主要专业化如下所示:

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

当您键入 Example&lt;stuff goes here&gt; 时,它总是与主要特化的 &lt;typename A, typename... Args&gt; 参数列表匹配。

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

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

这是一个次要专业。这里,

template <typename A, typename... Args>

不是参数列表,而是演绎列表。

参数列表是:

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

这里。 &lt;&gt; 之间的内容仅用于模式匹配反对传递给主要专业化的参数。

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

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

【讨论】:

  • 我接受这个作为澄清定义和术语并解释它们如何在我没有接触过的更深层次上工作的答案。
【解决方案2】:

发生了什么?编译器是否试图将常量视为类型名?

是的。

如果typename可以特化为int,int可以特化为2,为什么typename不能特化为2?

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

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

用 int 或 enum 专门化类的“正确”方法是什么?

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

【讨论】:

    猜你喜欢
    • 2020-07-18
    • 2017-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多