Рассмотрим следующий упрощенный шаблон метапрограммирующего кода, который реализует Angle
класс, внутри которого хранится уменьшенное значение по модулю 360 градусов.
#include <iostream>
#include <typeinfo>
template<int N, int D>
struct Modulus
{
static auto const value = N % D;
};
template<int N>
struct Angle
{
static auto const value = Modulus<N, 360>::value; // ERROR
//static int const value = Modulus<N, 360>::value; // OK
//static auto const value = N % 360; // OK
typedef Angle<value> type;
};
int main()
{
std::cout << typeid(Angle<30>::type).name() << "\n";
std::cout << typeid(Angle<390>::type).name() << "\n";
return 0;
}
Выход на Ideone
С Visual C ++ 2010 Express я могу сделать static auto const = Modulus<N, 360>::value
, но с MinGW gcc 4.7.2 (Нувен дистрибутив) или Ideone (gcc 4.5.1) Я должен либо явно обозначить тип как static int const value = Modulus<N, 360>::value
или я должен использовать auto
с полным модульным выражением как static auto const value = N % 360;
,
Вопрос: Какой компилятор корректен в соответствии с новым стандартом C ++ 11?
Код действителен. Visual C ++ правильно принимает это, а gcc неправильно отклоняет его (для полноты, Clang 3.1 также принимает код). В спецификации говорится, что (C ++ 11 7.1.6.4 [dcl.spec.auto] / 4):
auto
Тип Спецификатор также может использоваться … при объявлении статического члена данных с скобки или равно-инициализатор который появляется внутри член-спецификация определения класса.
Ваш value
является статическим членом данных. Оно имеет скобки или равно-инициализатор (это = Modulus<N, 360>::value
часть декларации), и инициализатор появляется внутри член-спецификация определения класса (т. е. это то, что смертные могут назвать «встроенным инициализатором»).
Других решений пока нет …