有没有办法从变量设置模板参数?

Lar*_*ars 1 c++ templates

我有一个枚举值作为一个类的成员,我想作为模板参数传递?编译器抱怨该成员不能用于常量表达式.这项工作有什么神奇之处吗?

我目前的解决方案是一个switch-case语句,但在我的原始代码中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
}
Run Code Online (Sandbox Code Playgroud)

这些示例会生成以下错误:

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
Run Code Online (Sandbox Code Playgroud)

gre*_*olf 5

传递给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
}
Run Code Online (Sandbox Code Playgroud)