【问题标题】:C++: How to create enum within a function?C++:如何在函数中创建枚举?
【发布时间】:2011-04-24 17:41:35
【问题描述】:

我想通过不单独创建枚举列表来简化事情,而是沿着函数调用创建枚举,该函数调用创建我指向这些枚举的数据。

我尝试制作#define,它会创建另一个#define,但它不起作用:

int defcounter = 0;

#define make_def(enumname, somedata) \
    #define enumname defcounter \
    defcounter++; \
    func_call(somedata); \

void createstuff(){
    make_def(MY_ENUM_NAME, mydata);
    make_def(MY_OTHER_ENUMNAME, mydata);
}

void dostuff(){
    somefunc_call(MY_ENUM_NAME);
    somefunc_call(MY_OTHER_ENUMNAME);
}

但这会在#define enumname 处产生错误:

error C2162: expected macro formal parameter

我怎样才能做到这一点?

【问题讨论】:

  • 您应该在#define enumname defcounter 周围添加#ifdefs。你#define了两次。
  • @muntoo,我到底在哪里定义了两次?另外,如果我碰巧尝试定义一些东西两次,我认为它会产生编译错误是最好的。
  • @Rookie 你没有定义任何东西两次,但是宏 make_def 中的第二个 #define 尝试扩展标记“define”并引用它,但它不能,因为它没有定义,它导致我猜的错误
  • @Rookie:关于您要求编译器在#define'd 两次时生成错误(甚至是警告),这不是 C 预处理器的工作方式,而且也是几十年迟到了。
  • 问题是,我不明白你为什么要在运行时创建枚举值。如果你想在你的 somefunc_call 中对它们采取行动,你必须事先知道它们的值,因此你必须在编译时拥有它们。在这种情况下,为什么不创建一个普通的枚举呢?在另一种情况下......好吧,枚举只是一个整数类型,那么为什么不简单地使用一个 int (例如)?

标签: c++ visual-studio-2008 macros enums


【解决方案1】:

在 C++ 中,在运行时创建新类型(类、枚举、联合等)是不可能的。 C++ 的主要特点之一是它是静态类型的——所有类型都必须在编译时知道。

【讨论】:

  • 废话...还有其他方法可以做我正在做的事情吗?我不想为此创建一个字符串映射...
  • 如果您想在运行时创建,字符串映射正是您需要创建的。为什么不呢?
  • @Rookie 也许如果你问了一个没有假设解决方案的问题,我们可以告诉你 C++ 的方式来做你真正想做的任何事情。
【解决方案2】:

预处理器命令(#define#if#pragma#include、...)不能出现在宏/定义中。问题是,CPP(C 预处理器)用换行符分隔命令,而 C 和 C++ 不知道换行符。在 C/C++ 中,您可以将所有内容写在一行上,而对于预处理器命令,则不能。

#define MY_MACRO(name) \
    #define name##_macro something_cool \
    enum name{ \
      .... \
    }

// somewhere else
void myfunc(){
  MY_MACRO(myfunc_enum);
}

现在,在预处理时,由于\ 反斜杠,这些行都被粘成了一条大行:

#define MY_MACRO(name) #define name##_macro something_cool enum name{....}

现在,该宏将如何看待使用情况?

void myfunc(){
  #define name##_macro something_cool enum name{....};
}

现在,预处理器必须再次运行 #define。但究竟什么属于#define,什么不属于?对于编码人员来说,宏是在单独的行中编写时很清楚,但现在不再是了。

【讨论】:

    【解决方案3】:

    您想要的输出究竟是什么?您需要解释您认为可能从 C 预处理器得到的输出。

    您遇到范围问题,并试图在另一个宏的替换文本中定义一个宏。

    范围

    make_def() 调用未定义的函数“func_call”。 createstuff() 函数使用未定义的变量 mydata。而函数dostuff() 似乎调用了一个未定义的函数somefunc_call(),其中的枚举可能已经在一个单独的函数中定义了。

    如果在一个函数内部定义了枚举,则该枚举不可用于该函数外部的代码,特别是对于被调用函数或调用函数均不可用。仅此一项就限制了您似乎正在尝试做的事情的效用。 (是的,枚举值可能会隐式转换为int 或某种类似类型,但它并不是真正使用的枚举类型。)

    在宏中定义宏

    您不能创建一个本身在其替换文本中包含 #define 或任何其他预处理器指令的宏。

    如果调用外部宏,则扩展不会将内部 #define 解释为预处理器指令,因此它几乎总是以错误告终,在上下文中 # 必须是字符串化运算符,并且'define' 后面的单词必须是外部宏的参数名称才能起作用。

    // Does not work as intended
    #define macro(define, prefix) #define another(name)   foo(prefix ## name)
    macro(something, other);
    

    生成:

    "something" another(name)  foo(othername);
    

    C99 中的 _Pragma 是“宏扩展不能包含预处理器指令”的部分例外,但它 (_Pragma) 不以 # 开头。

    【讨论】:

      【解决方案4】:

      您的宏不正确,因为您不能使用宏来创建另一个宏,不幸的是,因为符号 # 在扩展列表中具有特殊含义:它可以引用宏参数或扩展另一个宏。一种简单(尽管设计不佳)的方法就是使用旧的 c 风格 #define MY_ENUM_NAME valueas c 宏不尊重范围,但这不是好的设计。另一种可能性是传入字符串参数并对它们进行哈希处理,但这一切都取决于你想要做什么。

      【讨论】:

        猜你喜欢
        • 2020-03-03
        • 2011-03-10
        • 1970-01-01
        • 2021-09-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-12
        相关资源
        最近更新 更多