【问题标题】:Using enum as template type argument in C++在 C++ 中使用枚举作为模板类型参数
【发布时间】:2010-08-14 23:04:42
【问题描述】:

在 C++ 中使用枚举作为模板(类型)参数是否有任何限制/问题?

例子:

enum MyEnum
{
    A, B, C, D, E
};

template <typename _t>
class MyTemplate
{
public:
   _t value;

   void func(const _t& param) { /* .... */ }
};

// ....

MyTemplate<MyEnum> MyInstance;

我在 Win32/x86 上通过 VS 2008 (SP1) 使用 MSVC++ 的实际问题是与使用枚举作为模板参数的类相关的几个编译错误(= 编译器报告的错误)。由于我的项目不幸变得有点复杂(您可以将其视为设计错误:P),引发这些错误的模板类是派生的、嵌套的,甚至专门用于具有枚举模板参数的类。

在尝试构建时,编译器在只有注释的行中报告了许多错误/无用的错误,例如“C2059: syntax error: 'public'”。其中许多我可以通过用 _t 替换类似于示例中的 const _t& 参数的方法来修复(即复制参数),但我既不能修复所有这些错误,也不知道为什么这个“有帮助” . **我知道,上面的简单示例编译时没有错误。

使用 int 而不是 enum,我的项目编译时没有错误。

提前感谢任何提示或提示!


编辑

毕竟,我认真地认为这是一个编译器错误。当我试图用简化的代码重现错误时,我只在所有“构建”的 50% 中得到了它们,不是很确定:
例如。试图编译,它报告了这些错误。重建 - 没有变化。删除了评论,构建 - 没有变化。重建 - 然后:没有错误,编译正常。

我已经遇到了一些编译器错误(我猜在 20k 行代码内有 2 或 3 个),但在我看来,这个错误很奇怪。
任何建议如何确定它是否编译器?

【问题讨论】:

  • “尝试构建时,编译器报告了许多错误/无用的错误” 这些“无用”错误通常非常详细地描述了哪里/哪里出了问题。只需读取编译器输出而不是“错误列表”。
  • 感谢您的提示,但我做到了。我总是这样做^^但这对我没有帮助...错误:错误C2059:语法错误:'public'错误C2143:语法错误:在';'之前缺少'>'错误 C2143:语法错误:缺少“;”在'}'之前致命错误C1004:发现意外的文件结尾(然后是一些其他错误,与此问题无关)所有这些仅在使用枚举时出现,在使用int时消失
  • 这对我来说看起来非常好。这要么是编译器错误,要么是你的错误,如果你要猜测,99.9% 的赌注就是你。但是您发布的sn-ps没有任何问题。请发布一个内部完整的小示例以及它创建的确切编译器错误。
  • 我同意 - 请参阅编辑。只是想知道为什么 int 类型编译得很好
  • 代码 sn-p 在我的 MSVC 编译器上编译良好,没有警告或错误!!

标签: c++ templates enums visual-c++-2008


【解决方案1】:

是的,有限制。例如,根据 C++03 14.3.1[temp.arg.type]/2,您不能使用匿名枚举作为模板参数。

本地类型、无链接类型、未命名类型或由这些类型中的任何一种复合而成的类型不得用作模板类型参数的模板参数。

所以下面的代码在 C++03 中是无效的:

template <typename T>
void f(T) {}

enum {A};

int main() {
  f(A);
}

它在 C++11 中有效。

【讨论】:

    【解决方案2】:

    参考原问题:

    在 C++ 中使用枚举作为模板(类型)参数是否有任何限制/问题?

    我没有找到任何东西——而且我认为没有。这可能是一个坏主意,因为这种技术并不经常使用,因此可能存在一些(更多)与此相关的编译器错误,正如 Potatoswatter 所说。
    考虑以下示例:

    enum MyEnum : int
    {
        A, B, C, D
    };
    
    template <typename _t> class MyTemplate
    {
    public:
        void print()
        {
            cout << "not using any specialisation" << endl;
        }
    };
        template <> class MyTemplate <MyEnum>
        {
        public:
            void print()
            {
                cout << "MyEnum specialisation" << endl;
            }
        };
        template<> class MyTemplate <int>
        {
        public:
            void print()
            {
                cout << "int specialisation" << endl;
            }
        };
    
    template <typename _t> void print(_t param)
    {
        MyTemplate<_t> m;
        m.print();
    }
    
    
    int main()
    {
        print(A);
        print(5);
    
        return 0;
    }
    

    输出是:

    MyEnum 专业化
    int专业化

    对于这些简单的示例,一切正常且符合预期,并且枚举可以与任何其他类型一样完美地作为模板类型参数(= 我看不出有任何问题的原因)。

    最初,我在问题中引入了示例来说明我对那个问题的意思(枚举作为模板类型参数,显示可能的用法作为成员或方法参数类型等等)。为了提供一些背景知识,即为什么我问了这个问题(想象我问“int 有什么问题”),我在编译我的实际项目时提到了这些奇怪的问题。
    很抱歉,我无法提取其本身完整的 sn-p 并重现错误,我能得到的最少是将 2k 行代码拆分为 4 个文件,其中出现“语法错误:'public'”和当我编译项目时引发了其他一些语法错误,并且在删除评论或重新构建(=删除中间文件)时,它们在某些情况下出现/消失。不幸的是,重建对原始项目没有帮助,我不得不将特化从枚举类型替换为 int。

    所以,感谢大家的提示和提示。在我看来,根本问题是一个编译器错误,是什么让这个问题变得毫无意义,因为答案似乎只是 “不 - 使用枚举作为模板类型参数没有任何限制”。很抱歉给您带来不便。

    【讨论】:

      【解决方案3】:

      MSVC 奇怪地处理枚举(值)模板参数。枚举有时会不正确地提升为int,并且运算符定义不正确。看来他们并没有真正用enum 类型测试模板引擎。

      证明它是一个编译器错误很简单:将有效代码放入并观察它是否成功编译。 你的例子显然是合规的,所以问题(或错误,无论如何)是他们的。

      编辑:仔细检查后,您说该示例没有重现了该错误。在您提供一个可以帮助您的示例之前,我们或其他任何人都无法帮助您。

      【讨论】:

      • 只能通过两种方式证明编译器存在错误:a) 根据相关标准进行验证 b) 阅读文档并检查它是否是已知问题/缺陷
      • OP 没有提供枚举 value 作为模板参数 - 枚举 type 是参数。
      猜你喜欢
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多