如果您enum class
按照建议的方式使用 C++11,包括命名空间,确实需要两个限定符来访问它们:Colour::Colour::RED
,您可能会觉得这很烦人。
但是,我认为将from_string
andto_string
函数放入命名空间中没有用——无论是出于类型安全还是出于任何其他原因。
to_string()
适用于多种类型,不仅Colour
. 事实上,从 C++11 开始,甚至std::to_string
还有std::string
. 简单地扩展该概念以涵盖用户定义的类型是有意义的:
template <typename T>
std::string to_string(const T arg)
{ return std::to_string(arg); }
template <>
std::string to_string(const Color c)
{
switch (c)
{
case Color::red:
return "red";
case Color::green:
return "green";
case Color::blue:
default:
return "blue";
}
}
然后您可以使用to_string(42)
as well to_string(Color::red)
,这是完全类型安全的(与任何函数重载/模板特化一样类型安全)。
同样对于from_string
:
template <typename T>
T from_string(const std::string &str);
template <>
Color from_string<Color>(const std::string &str)
{
if (str == "red")
return Color::red;
else if (str == "green")
return Color::green;
else if (str == "blue")
return Color::blue;
else
throw std::invalid_argument("Invalid color");
}
我只提供了 的实现Color
,但为其他类型添加它会很简单。
使用 this 是类型安全的,并且Color
仅在必要时才需要显式指定(作为模板参数或范围限定符),而不需要重复:
int main()
{
Color c = Color::red;
std::cout << to_string(c) << std::endl;
c = from_string<Color>("red");
return 0;
}
(如果您害怕名称冲突,或者通常不想将任何东西放在全局范围内,您可以将to_string
andfrom_string
放入命名空间convert
并将它们用作convert::from_string<Color>("red")
等。甚至,创建一个类模板convert
以便您可以将其称为convert<Color>::from_string("red")
,这会产生非常易于准备、直观的代码。)