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

时间:2012-01-27 07:51:08

标签: 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
}

示例会产生以下错误:

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

2 个答案:

答案 0 :(得分: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
}

答案 1 :(得分:3)

不,模板扩展在编译时完成。只有在编译程序时已知该值时,它才有效。

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