编译时编号的字符串文字

时间:2017-02-28 11:53:47

标签: c++ enums macros constexpr

我正在努力将许多宏转换为(范围内的,类型安全的)const值。我的目标是在必要时使用if constexpr

目前,我已经设法使用stringify宏和模板函数获得了一些令人满意的结果:

#define STRINGIFY(X) #X
#define TO_STRING(X) STRINGIFY(X)

上面的宏有一个令人惊讶的不同的行为,具体取决于给定的参数:

std::cout << TO_STRING(_DEBUG) << '\n';

显示_DEBUG是否(且仅当)宏_DEBUG 未定义,但如果已定义则显示宏值(如果已定义,则显示空字符串,但不显示值)。

无论如何,宏结果总是text literal所以我使用constexpr函数检查结果:

template <int SIZE>
constexpr bool b(const char (&definition)[SIZE])
{
    return definition[0] != '_';
}

现在合并STRINGIFYb,可以创建枚举并在if constexpr中使用它们(而不是使用#ifdef个链):

enum operating_system : bool
{
    iOS     = b(TO_STRING(__APPLE__)),
    Windows = b(TO_STRING(__MINGW32__)),
    Linux   = b(TO_STRING(__linux__)),
};

int main()
{
    if constexpr (operating_system::Windows)
    {
        // Specific Windows stuff.
    }
    else if constexpr (operating_system::iOS)
    {
        // Specific iOS stuff.
    }

    // Platform-independent sutff.

    return 0;
}

我不喜欢使用辅助函数将文字转换为bool值(b函数),但这并不是什么大问题。真正的问题是它依赖于检测起始下划线(_)以便检测不存在的宏。因此,具有以下划线开头的值的现有宏将是误报。此外,宏的实际值丢失了,让我们看一个例子:

#define _DEBUG 0
#define DRIVERS _09072007

template <int SIZE>
constexpr int i(const char (&definition)[SIZE])
{
    return definition[0] != '_'; // what shall I put here?...
}

enum stuff : int
{
    cpp_version     = i(TO_STRING(__cplusplus)),
    debug_enabled   = i(TO_STRING(_DEBUG)),
    drivers_version = i(TO_STRING(DRIVERS)),
};

int main()
{
    std::cout << "C++ version: "     << stuff::cpp_version << '\n'
              << "Debug mode: "      << stuff::debug_enabled << '\n'
              << "Drivers version: " << stuff::drivers_version << '\n';

    return 0;
}

上面的代码显示:

C++ version: 1
Debug mode: 1
Divers version: 0

预期但不满意。我需要一种方法将这些字符串文字转换为实际值(在编译时),以及“{em>它存在,如果不是以下划线开头”的天真方法的解决方法{{1}宏显示(可能忽略非数字值,直到找到数值?)。

我尝试过递归方法,但索引字符串文字不是常量表达式:

DRIVERS

0 个答案:

没有答案