Этот вопрос касается взаимосвязи между шаблонами и статическими интегральными константами в Visual Studio C++ 2013 с флагом/Za. Это имеет значение для библиотеки ускорения.Статические константы целочисленного типа C++: вне определения класса
Во-первых, давайте проверим код без шаблонов:
struct easy
{
static const int a = 5;
const int b;
easy(int b_) : b(std::max(b_, a))
{}
};
const int easy::a;
int main()
{
easy d_Easy(0);
return 0;
}
Согласно странице руководства для compiler option /Za: «В соответствии со стандартом (/ Za), вы должны сделать вне класса определение членов данных ". Пример на этой странице и вышеприведенный код объявляют статическую константу внутри класса и определяют ее значение там. Необходимость определения класса не объясняется в this link.
Теперь, давайте посмотрим на проблему с шаблонами.
template< class T >
struct problem
{
static const int a = 5;
const int b;
problem(int b_) : b(std::max(b_, a))
{}
};
template< class T >
const int problem<T>::a;
int main()
{
problem<char> d_Bad(666);
return 0;
}
При компиляции с/Za, компоновщик выдает сообщение об ошибке "LNK2019: неразрешенный внешний символ". Эта ошибка не появляется с опцией /Ze. Основная проблема заключается в том, что некоторые дополнительные библиотеки используют BOOST_STATIC_CONSTANT и BOOST_NO_INCLASS_MEMBER_INITIALIZATION в коде, подобном описанному выше snipet.
Взлом некоторые из них:
template< class T >
struct fixed
{
static const int a;
const int b;
fixed(int b_) : b(std::max(b_, a))
{}
};
template< class T >
const int fixed<T>::a = 5;
int main()
{
fixed<char> d_Good(777);
return 0;
}
Этот код в настоящее время составляет с/Za.
Вопросы:
1) Что стандарт C++ 11 говорят о шаблонах и статических интегральных констант? Могут ли/они должны иметь определение класса, но их значение должно быть указано в определении класса?
2) Есть ли у подголовника обходные пути?
UPDATE
Важно держать std::max
в коде, потому что (я думаю), он пытается получить ссылку на его параметры. Если вы используете b_<a
, тогда компилятор просто оптимизирует эти константы.
_ «Если вы используете b_ sehe
Возможно, последний параграф моего ответа необходим для вашего реального вопроса?Если это так, очевидно, вам ** всегда ** необходимо отделить статическую инициализацию элемента в отдельную единицу перевода. – sehe
@sehe: это актуально, потому что я не могу скомпилировать boost :: pool с/Za в Visual Studio C++ 13. Я проследил виновника в поведении в вопросе. После того, как я узнаю, кто несет ответственность, я сообщаю об ошибке либо людям с повышенным интересом, либо репатриантам MS. – Hector