Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何将类链接到枚举?_C++_Templates_Enums - Fatal编程技术网

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);
}