Есть ли способ установить параметр шаблона из переменной? - PullRequest
1 голос
/ 27 января 2012

У меня есть значение перечисления в качестве члена класса, который я хочу передать в качестве аргумента шаблона? Компилятор жалуется, что член нельзя использовать в константном выражении. Есть ли магия, чтобы получить эту работу?

Мое текущее решение - это оператор переключения, но в моем исходном коде 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 ]

5 голосов
/ 27 января 2012

Аргументы шаблона, передаваемые в 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
}
3 голосов
/ 27 января 2012

Нет, расширение шаблона выполняется во время компиляции.Это работает, только если значение известно при компиляции программы.

Компилятор также запрашивает константное выражение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...