有没有一种方法可以从变量中设置模板参数

Is there a way to set a template parameter from a variable?

本文关键字:变量 设置 参数 方法 一种 有没有      更新时间:2023-10-16

我有一个枚举值作为类的成员,我想把它作为模板参数传递?编译器抱怨不能在常量表达式中使用该成员。有什么魔法可以完成这项工作吗?

我当前的解决方案是一个switchcase语句,但在我的原始代码EType中有近200个条目。因此,我最初的想法是编写一个type_traits,用于将枚举值映射到类型。

下面是我的问题的一个例子(也在ideone.com上)(问题是main()中的最后一行):

#include <iostream>
enum EType
{
    eType_A,
    eType_B,
    eType_C
};
struct Foo
{
    Foo(EType eType)
        : m_eType(eType)
    {
    }
    EType m_eType;
};
template <EType eType>
struct Bar
{
    static std::string const toString()
    {
        return "-";
    }
};
template <>
struct Bar<eType_A>
{
    static std::string const toString()
    {
        return "A";
    }
};
template <>
struct Bar<eType_B>
{
    static std::string const toString()
    {
        return "B";
    }
};
int main(int argc, char *argv[])
{
    std::cout << "Bar<eType_A>::toString()=" << Bar<eType_A>::toString() << "n";
    std::cout << "Bar<eType_B>::toString()=" << Bar<eType_B>::toString() << "n";
    std::cout << "Bar<eType_C>::toString()=" << Bar<eType_C>::toString() << "n";
    Foo stFooA(eType_A);
    std::cout << "Bar<stFooA.m_eType>::toString()=" << Bar<stFooA.m_eType>::toString() << "n"; // <--- here ist the problem
}

示例生成以下错误:

prog.cpp: In function ‘int main(int, char**)’:
prog.cpp:54: error: ‘stFooA’ cannot appear in a constant-expression
prog.cpp:54: error: `.' cannot appear in a constant-expression
prog.cpp:54: error: template argument 1 is invalid

传递到Bar的模板参数在编译时必须是已知的。您会得到这个错误,因为stFooA.m_eType可能在运行时发生更改,因此无法工作。

为了回答你的另一个问题,让它发挥作用有什么魔力吗?也许——您允许在编译时公开m_eType的值吗?如果这对你的问题是一个有效的约束,你可以把它改成这样,它就会起作用:

// ...
template <EType eType>
struct Foo
{
    Foo()
    {
    }
    static const EType m_eType = eType;
};
int main(int argc, char *argv[])
{
    std::cout << "Bar<eType_A>::toString()=" << Bar<eType_A>::toString() << "n";
    std::cout << "Bar<eType_B>::toString()=" << Bar<eType_B>::toString() << "n";
    std::cout << "Bar<eType_C>::toString()=" << Bar<eType_C>::toString() << "n";
    Foo<eType_A> stFooA;
    std::cout << "Bar<stFooA.m_eType>::toString()=" 
              << Bar<Foo<eType_A>::m_eType>::toString() 
              << "n"; // Foo<eType_A>::m_eType is known at compile-time so this works
}

否,模板扩展是在编译时完成的。只有在编译程序时知道该值时,它才起作用。

编译器还要求一个常量表达式。