所以我有一个在GCC中运行良好的宏,但在微软的C++编译器中没有.我希望有人可能知道一种解决方法,或者也许可以向我解释它为什么会这样.
我确定这个宏并不完全是"标准",但它确实会帮助我.
这是宏的一个功能示例:
#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, N, ...) N
#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1)
#define FULLY_EXPANDED(count, ...) \
MAC ## count (__VA_ARGS__)
#define SEMI_EXPANDED(count, ...) FULLY_EXPANDED(count, __VA_ARGS__)
#define EXPAND_THESE(...) SEMI_EXPANDED(VA_NARGS(__VA_ARGS__), __VA_ARGS__)
#define ACTUAL_MACRO(x) parent->GetProperty<x>();
#define MAC1(a) ACTUAL_MACRO(a)
#define MAC2(a,b) MAC1(a) ACTUAL_MACRO(b)
#define MAC3(a,b,c) MAC2(a,b) ACTUAL_MACRO(c)
#define MAC4(a,b,c,d) MAC3(a,b,c) ACTUAL_MACRO(d)
#define MAC5(a,b,c,d,e) MAC4(a,b,c,d) ACTUAL_MACRO(e)
Run Code Online (Sandbox Code Playgroud)
以下是我如何使用此宏:
struct MyStructure
{
void Foo()
{
EXPAND_THESE(Property1, Property2, Property3, Property4)
}
Base * parent;
}
Run Code Online (Sandbox Code Playgroud)
以下是GCC如何扩展上述内容:
struct MyStructure
{
void …Run Code Online (Sandbox Code Playgroud) 假设我#define在外部库的头文件中有一个s 列表.这些#define代表从函数返回的错误代码.我想编写一个转换函数,它可以将错误代码作为输入,并作为输出返回表示实际#define名称的字符串文字.
举个例子,如果我有
#define NO_ERROR 0
#define ONE_KIND_OF_ERROR 1
#define ANOTHER_KIND_OF_ERROR 2
Run Code Online (Sandbox Code Playgroud)
我想要一个能够调用的函数
int errorCode = doSomeLibraryFunction();
if (errorCode)
writeToLog(convertToString(errorCode));
Run Code Online (Sandbox Code Playgroud)
并且convertToString()能够自动转换该错误代码,而不是一个巨大的开关盒
const char* convertToString(int errorCode)
{
switch (errorCode)
{
case NO_ERROR:
return "NO_ERROR";
case ONE_KIND_OF_ERROR:
return "ONE_KIND_OF_ERROR";
...
...
...
Run Code Online (Sandbox Code Playgroud)
我有一种感觉,如果这是可能的,那么可以使用模板和元编程,但这只会使错误代码实际上是一种类型,而不是一堆处理器宏.
可能重复:
枚举到字符串:如果无效/未找到,则返回枚举整数值
简而言之,我所拥有的(工作)定义代码是这样的:
enum Gadget
{
First,
Second,
};
const char* gadget_debug_names[] = {
"First",
"Second",
// note: strings are same as enum tokens here, but bonus points if
// they can optionally be given different values
};
Run Code Online (Sandbox Code Playgroud)
但是,如果信息位于必须手动维护的多个单独位置,则容易出错.(在某些情况下,在代码库中,我正在使用这两个 - 或更多 - 地方甚至不在同一个文件中.)所以,将这些东西命名一次真的很棒.
现在我们可以使用代码生成和声明性数据文件来完成此操作,但是如果有更好的方法,我宁愿不向现有的构建过程添加另一个步骤.拥有看起来像的东西是完美的
DEFINE_GADGET(First)
DEFINE_GADGET(Second)
Run Code Online (Sandbox Code Playgroud)
(如果需要,可选择启动/停止宏)但是,由于宏只是纯文本替换,我无法想出让预处理器在写出枚举定义时"记住"标记的任何方法.
我认为这也可能通过元编程实现,但我对如何做到这一点感到茫然.我在那里看到的所有例子都涉及递归地构建数据结构.我可以看到我如何以这种方式构建字符串数组,但我不确定如何传递令牌名称,或者如何构建枚举.(当然,使用元编程来构建一个字符串数组会非常荒谬.)
有没有办法让我在这里保持DRY,而不使用代码生成?
经典的C++枚举没有直接的方法来检测重复值.
这个问题是在新的C++ 11中解决的enum class吗?
enum class ConnectionState : uint32_t
{
Connecting,
Reconnecting = 2,
Disconnecting,
LocalConnection,
NoNetwork = 2,
WifiNetwork,
Last
}
Run Code Online (Sandbox Code Playgroud) 我有以下enum描述错误代码:
typedef enum {
et_general = 0,
et_INVALID_CLI_FLAG = 1,
...
et_undef = 500
} EErrorType;
Run Code Online (Sandbox Code Playgroud)
我明确写入枚举值的主要原因是为了简化调试过程.
无论如何,我想知道是否有办法让编译器抱怨非唯一值.我总是可以在运行时轻松检查它,但我想避免这种情况.
我已经阅读了这篇文章并回顾了这个答案.据我了解,这个答案建议以这样的方式产生枚举,使其" 更容易犯错误 ".
我想保留enum定义,或者接近它.
我正在尝试制作一个简单的预处理器循环.(我意识到这是一个可怕的想法,但是很好.)
// Preprocessor.h
#ifndef PREPROCESSOR_LOOP_ITERATION
#define MAX_LOOP_ITERATION 16 // This can be changed.
#define PREPROCESSOR_LOOP_ITERATION 0
#endif
#if (PREPROCESSOR_LOOP_ITERATION < MAX_LOOP_ITERATION)
#define PREPROCESSOR_LOOP_ITERATION (PREPROCESSOR_LOOP_ITERATION + 1) // Increment PREPROCESSOR_LOOP_ITERATION.
#include "Preprocessor.h"
#endif
Run Code Online (Sandbox Code Playgroud)
问题是它看起来不像PREPROCESSOR_LOOP_ITERATION是递增的,所以它只是无限地包含它自己.如果我将该行更改为实际整数(如17),则预处理器会#include正确跳过该指令.
我做错了什么?