模板类型的成员枚举类作为函数参数

时间:2019-12-12 20:45:27

标签: c++ c++11

我想创建一个以参数为参数的模板函数,而不是模板类型本身,而是模板类型的成员枚举类。这可能吗?

以下代码演示了我想要实现的目标,我想知道是否有一些模板魔术可以为我完成目标。

#include <iostream>

using namespace std;

class A{
public:
    enum class ID {a1, a2};

    static void f(ID id){
        switch(id){
        case ID::a1:
            std::cout << "a1\n";
            break;
        case ID::a2:
            std::cout << "a2\n";
            break;
        }
    }
};

class B{
public:
    enum class ID {b1};

    static void f(ID id){
        switch(id){
        case ID::b1:
            std::cout << "b1\n";
            break;
        }
    }
};

template<typename TypeName>
void g(TypeName::ID id){
    TypeName::f(id);
}

int main(int argc, char **argv){
    g(A::ID::a1);
    g(A::ID::a2);
    g(B::ID::b1);

    return 0;
}

所需的输出为

a1
a2
b1

尤其要注意我如何让函数g以TypeName :: ID作为参数而不是TypeName。

首选C ++ 11解决方案,但也需要使用更高版本的解决方案。

2 个答案:

答案 0 :(得分:3)

#include <iostream>

using namespace std;

class A{
public:
    enum class ID {a1, a2};

    static void f(ID id){
        switch(id){
        case ID::a1:
            std::cout << "a1\n";
            break;
        case ID::a2:
            std::cout << "a2\n";
            break;
        }
    }
};

class B{
public:
    enum class ID {b1};

    static void f(ID id){
        switch(id){
        case ID::b1:
            std::cout << "b1\n";
            break;
        }
    }
};

template<typename TypeName>
void g(typename TypeName::ID id){
    TypeName::f(id);
}

int main(int argc, char **argv){
    g<A>(A::ID::a1);
    g<A>(A::ID::a2);
    g<B>(B::ID::b1);

    return 0;
}

答案 1 :(得分:2)

template<typename TypeName>
void g(TypeName::ID id){ // WRONG
    TypeName::f(id);
}

需要typename

template<typename TypeName>
void g(typename TypeName::ID id){
    TypeName::f(id);
}

但是,类型是不可推论的(由于::)。 因此在呼叫站点,您必须指定类型:

g<A>(A::ID::a1);
g<A>(A::ID::a2);
g<B>(B::ID::b1);

或者,为了保持预期的呼叫站点语法,您可以创建特征以将(枚举)类型绑定到类:

template <typename E> struct ClassFromId;

template <> struct ClassFromId<A::ID> { using type = A; };
template <> struct ClassFromId<B::ID> { using type = B; };


template<typename E>
void g(E id){
    ClassFromId<E>::type::f(id);
}

Demo