我有以下代码:
#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);
}
如何安排在decoder
中调用相应的助手类(HobbitHelper或Apprentice)?我无法在枚举中声明嵌套类型,就像它是一个类一样。我也尝试从枚举中派生助手(因为助手本身没有数据),但也不允许这样做。
有什么想法吗?
答案 0 :(得分:4)
您可以在枚举类型上将helper
类型特征设为外部和模板,并为每个enum
明确专门化:
template <typename T> struct type_is { using type = T; };
template <typename > struct helper;
template <> struct helper<Hobbit> : type_is<HobbitHelper> { };
template <> struct helper<Wizard> : type_is<Apprentice> { };
template <typename T>
using helper_t = typename helper<T>::type;
然后decode
才能访问:
template <typename T>
T decoder(std::string s)
{
return helper_t<T>::decode(s);
}
答案 1 :(得分:1)
我的建议是部分模板专业化,虽然@Barry的答案可能更像你正在寻找的。 p>
+--------------------------------------+------------------------------------+-------+----------+---------+------------+-------------------------------+------------------+
| Alarm ID | Name | State | Severity | Enabled | Continuous | Alarm condition | Time constraints |
+--------------------------------------+------------------------------------+-------+----------+---------+------------+-------------------------------+------------------+
| 50d52c2f-fdaf-4767-818d-3cfd91c1848a | simple-cpu_alarm_high-26y5dsoucoub | alarm | low | True | True | cpu_util > 0.1 during 1 x 60s | None |
+--------------------------------------+------------------------------------+-------+----------+---------+------------+-------------------------------+------------------+
答案 2 :(得分:1)
最简单的方法是使用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 ++库所采用的解决方案 - 或多或少。基本上没有额外的努力。我甚至没有提及向导。
答案 3 :(得分:1)
除了帮助问题之外,还有比级联if
更好的解决方案:
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;
}