我需要通过为其实现宏来使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
我必须承认:宏很有趣。我们大家都应该知道应该避免使用它们。但是,由于这是有关宏的练习,因此我们可以将是否使用宏的讨论放在一边。
练习的重点是您不能(直接)打开std::string
。 This 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
实际名称的引用。
您可能要做什么来打开字符串:
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; }
}
}