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

问题描述 投票:-3回答:2

我需要通过为其实现宏来使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;
        }
    }
}

我想在tag中使用SWITCH_STRING(tag)参数并将其与letter中的STRING_CASE(letter)参数进行比较,以实现像语法这样的开关,我被困了一段时间,对c ++中的宏还是陌生的您能否提供有关如何实现宏的解决方案?

#include <iostream>
#include <string>

// Write macros here | 
#define SWITCH_STRING(tag)
#define STRING_CASE(letter) letter == tag ? true : false
#define STRING_ELSE
c++ macros switch-statement
2个回答
1
投票

我必须承认:宏很有趣。我们大家都应该知道应该避免使用它们。但是,由于这是有关宏的练习,因此我们可以将是否使用宏的讨论放在一边。

练习的重点是您不能(直接)打开std::stringThis answer显示了如何解决此限制。由于需要编写极其冗长的重复代码,因此该宏是合理的。为了完整起见,我想添加如何使用您的原始方法,使用一系列的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,这在相互排斥的情况下应该是首选,这不是很好。但是,每种情况下return的结果都不会不同(如果不是这种情况,则您必须添加另一个回答中概述的goto vodoo)。有了它,很容易看出需要什么宏:

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

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

Full example


1
投票

您可能要做什么来打开字符串:

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; }
    }
}

不需要MACRO。

如果您遇到案例冲突,编译将失败(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; }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.