c ++宏使用来自另一个宏的变量

c++ macro using variable from an other macro

我需要通过为它实现宏来编译 foo:

int foo(std::string tag)
{
    SWITCH_STRING(tag)
    {
        STRING_CASE(a)
        {
            return 1;
        }

        STRING_CASE(b)
        {
            return 2;
        }

        STRING_CASE(abc)
        {
            return 3;
        }

        STRING_ELSE
        {
            return -1;
        }
    }
}

我想使用 SWITCH_STRING(tag) 中的 tag 参数并将其与 STRING_CASE(letter) 中的 letter 参数进行比较,以实现这种类似语法的开关,我'我卡住了一段时间,对 c++ 中的宏不熟悉,请问您能提供一个解决宏的方法吗?

#include <iostream>
#include <string>

// Write macros here | 
#define SWITCH_STRING(tag)
#define STRING_CASE(letter) letter == tag ? true : false
#define STRING_ELSE

打开字符串可能需要做的事情:

constexpr std::size_t myhash(std::string_view) { /* .. */ }

int foo(const std::string& tag)
{
    switch (tag)
    {
        case myhash("a"): { return 1; }
        case myhash("b"): { return 2; }
        case myhash("abc"): { return 3; }
        default: { return -1; }
    }
}

那不需要宏。

如果您与您的案例发生冲突,编译将失败(switch 中的值相同) 你将需要另一个哈希函数。

如果你想防止冲突(从输入字符串),你可以这样做:

constexpr std::size_t myhash(std::string_view) { /* .. */ }

int foo(const std::string& tag)
{
    switch (tag)
    {
        case myhash("a"): { if (tag != "a") { goto def; } return 1; }
        case myhash("b"): { if (tag != "b") { goto def; } return 2; }
        case myhash("abc"): { if (tag != "abc") { goto def; } return 3; }
        default: { def: return -1; }
    }
}

使用 MACRO

可能确实不那么冗长
#define CaseHash(str, c) case myhash(c): if (str != c) { goto def; }
#define DefaultHash default: def

结果为

constexpr std::size_t myhash(std::string_view) { /* .. */ }

int foo(const std::string& tag)
{
    switch (tag)
    {
        CaseHash(tag, "a") { return 1; }
        CaseHash(tag, "b") {  return 2; }
        CaseHash(tag, "abc") {  return 3; }
        DefaultHash: { return -1; }
    }
}

我不得不承认:宏可以很有趣。我们都应该知道应该避免它们。不过,由于这是一个关于宏的练习,我们可以把是否使用宏的讨论放在一边。

练习的重点是您不能(直接)打开 std::string 显示了如何解决此限制。被要求编写极其冗长的重复代码,宏是有道理的。为了完整起见,我想添加如何使用您原来的方法解决它,使用一系列 if 而不是 switch

首先,我编写了不涉及任何宏的函数来执行所要求的操作:

int foo(std::string tag)
{
    std::string& temp = tag;
    {
        if (temp == "a") 
        {
            return 1;
        }
        if (temp == "b")
        {
            return 2;
        }
        if (temp == "abc")
        {
            return 3;
        }
        {
            return -1;
        }
    }
}

它使用 if 而不是 else if 并不是很好,在互斥情况下应该首选它。但是,对于每种情况 returns,结果不会有所不同(如果不是这种情况,您将必须添加一些 goto vodoo,如其他答案中所述)。有了这些,就很容易看出需要什么宏了:

#define SWITCH_STRING(tag) std::string& temp = tag;
#define STRING_CASE(X) if (temp == #X)
#define STRING_ELSE

这就回答了你关于如何在第二个宏中使用一个宏的参数的问题:你不会。相反,您可以使用名称不再依赖于 tag 的实际名称的引用。

Full example