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
并不是很好,在互斥情况下应该首选它。但是,对于每种情况 return
s,结果不会有所不同(如果不是这种情况,您将必须添加一些 goto
vodoo,如其他答案中所述)。有了这些,就很容易看出需要什么宏了:
#define SWITCH_STRING(tag) std::string& temp = tag;
#define STRING_CASE(X) if (temp == #X)
#define STRING_ELSE
这就回答了你关于如何在第二个宏中使用一个宏的参数的问题:你不会。相反,您可以使用名称不再依赖于 tag
的实际名称的引用。
我需要通过为它实现宏来编译 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
并不是很好,在互斥情况下应该首选它。但是,对于每种情况 return
s,结果不会有所不同(如果不是这种情况,您将必须添加一些 goto
vodoo,如其他答案中所述)。有了这些,就很容易看出需要什么宏了:
#define SWITCH_STRING(tag) std::string& temp = tag;
#define STRING_CASE(X) if (temp == #X)
#define STRING_ELSE
这就回答了你关于如何在第二个宏中使用一个宏的参数的问题:你不会。相反,您可以使用名称不再依赖于 tag
的实际名称的引用。