不了解 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 不匹配
问题:
首先,我是泛型编程的新手,希望我问的是正确的问题。编译器规范术语对我来说还是有点陌生。
- 这是怎么回事?编译器是否试图将常量视为
类型名称?
- 如果 typename 可以特化为 int,int 可以特化为 2,为什么 typename 不能特化为 2?
- 用 int 或 enum 专门化 class 的 "proper" 方法是什么?
- 我问的问题对吗?
谢谢
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",我不会在这里讨论其规则。
我正在努力思考模板特化,但我有点困惑(可能不理解 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 不匹配问题:
首先,我是泛型编程的新手,希望我问的是正确的问题。编译器规范术语对我来说还是有点陌生。
- 这是怎么回事?编译器是否试图将常量视为 类型名称?
- 如果 typename 可以特化为 int,int 可以特化为 2,为什么 typename 不能特化为 2?
- 用 int 或 enum 专门化 class 的 "proper" 方法是什么?
- 我问的问题对吗?
谢谢
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",我不会在这里讨论其规则。