C++ 如何将类链接到枚举?
我有以下代码:C++ 如何将类链接到枚举?,c++,templates,enums,C++,Templates,Enums,我有以下代码: #include <string> enum class Hobbit { // typedef HobbitHelper helper; UNKNOWN = -1, Bilbo, Frodo, Samwise }; struct HobbitHelper { static Hobbit decode(std::string const& s) { if (s == "Bilbo") { re
#include <string>
enum class Hobbit {
// typedef HobbitHelper helper;
UNKNOWN = -1, Bilbo, Frodo, Samwise
};
struct HobbitHelper {
static Hobbit decode(std::string const& s) {
if (s == "Bilbo") {
return Hobbit::Bilbo;
}
else if (s == "Frodo") {
return Hobbit::Frodo;
}
else if (s == "Samwise") {
return Hobbit::Samwise;
}
else {
return Hobbit::UNKNOWN;
}
}
};
enum class Wizard {
// typedef Apprentice helper;
UNKNOWN = -1, Gandalf, Radagast, Saruman
};
struct Apprentice { // WizardHelper :)
static Wizard decode(std::string const& s) {
if (s == "Gandalf") {
return Wizard::Gandalf;
}
else if (s == "Radagast") {
return Wizard::Radagast;
}
else if (s == "Saruman") {
return Wizard::Saruman;
}
else {
return Wizard::UNKNOWN;
}
}
};
template <typename T>
T
decoder(std::string s)
{
return ??::decode(s);
// if the typedefs were allowed, I could use T::helper::decode()
}
int main()
{
std::string s{ "Rincewind" };
auto h = decoder<Hobbit>(s);
auto w = decoder<Wizard>(s);
}
我如何安排调用合适的助手类HobbitHelper或decoder中的学徒?我不能在枚举中声明嵌套类型,就好像它是一个类一样。我还尝试从枚举中派生助手,因为助手本身没有数据,但这也是不允许的
有什么想法吗?您可以将helper类型特性设置为外部,并在枚举类型上进行模板化,每个枚举都有一个显式的专门化:
我的建议是部分模板专门化,尽管@Barry的答案可能更像您所寻找的
template <typename T>
T decoder(std::string s);
template<>
Hobbit decoder(std::string s)
{
return HobbitHelper::decode(s);
}
template<>
Wizard decoder(std::string s)
{
return Apprentice::decode(s);
}
最简单的方法是使用ADL。您可以使用类型标记使编译器看起来在适当的命名空间中 考虑:
template<typename T> struct adl_tag {};
namespace MiddleEarth {
enum class Hobbit {
// typedef HobbitHelper helper;
UNKNOWN = -1, Bilbo, Frodo, Samwise
};
Hobbit decode(std::string const& s, adl_tag<Hobbit>) {
if (s == "Bilbo") {
return Hobbit::Bilbo;
}
else if (s == "Frodo") {
return Hobbit::Frodo;
}
else if (s == "Samwise") {
return Hobbit::Samwise;
}
else {
return Hobbit::UNKNOWN;
}
}
}
template<typename T> T decode(std::string s) {
return decode(s, adl_tag<T>());
}
<这是几乎所有C++库所使用的解决方案——或多或少。基本上不需要额外的努力。我甚至不必提及向导。除了帮助器问题,还有比级联更好的解决方案,如果:
最后,我使用了一个稍微修改过的版本 因为它让我写得更容易记忆
template <typename T>
T
decoder(std::string s)
{
return enumclass<T>::helper::decode(s);
}
所有的专业化都可以分布,即enumclass在hobbit.h中;enumclass位于wizard.h中。所有这些头文件都必须包含一个带有非专用模板的小头文件。虽然我越来越不喜欢helper这个词,但这是一个非常优雅的答案。这个解决方案也是可分发的:模板结构helper:type_是{};专门化可以位于相应的标题中。将helper\u t重命名为helper\u of会让它更容易记忆。Hobbit和Wizard都在MiddleEarth名称空间中:如果Hobbit解码,我看不出这有什么用。。。。。。不是一个自由函数,而是一个静态成员,例如原始问题中的HoBiStupLe.@ Bead My:把这些函数作为类的静态成员是C++中的一个坏实践,它是一个无意义的JavaSIST,并锁定了许多语言更有用的特性,如ADL。如果你把这样的函数放在一个类中,你会遇到比一点混乱的调用语法更大的问题。我确信你已经忘记了专门化中的参数,但它编译时确实没有这些参数。。。对不起!编辑:我在这里确实学到了一些东西。谢谢你:
template<typename T> struct adl_tag {};
namespace MiddleEarth {
enum class Hobbit {
// typedef HobbitHelper helper;
UNKNOWN = -1, Bilbo, Frodo, Samwise
};
Hobbit decode(std::string const& s, adl_tag<Hobbit>) {
if (s == "Bilbo") {
return Hobbit::Bilbo;
}
else if (s == "Frodo") {
return Hobbit::Frodo;
}
else if (s == "Samwise") {
return Hobbit::Samwise;
}
else {
return Hobbit::UNKNOWN;
}
}
}
template<typename T> T decode(std::string s) {
return decode(s, adl_tag<T>());
}
static Hobbit decode(std::string const& s) {
static std::unordered_map<std::strinng,Hobbit> choice {
{ "Bilbo", Hobbit::Bilbo },
{ "Frodo", Hobbit::Frodo },
{ "Samwise", Hobbit::Samwise }
};
auto f = choice.find( s );
return f != choice.end() ? f->second : Hobbit::UNKNOWN;
}
template <typename T>
struct enumclass {
};
template<>
struct enumclass<Hobbit> {
using helper = HobbitHelper;
};
template<>
struct enumclass<Wizard> {
using helper = Apprentice;
};
template <typename T>
T
decoder(std::string s)
{
return enumclass<T>::helper::decode(s);
}