Авто + статическая инициализация константы в классе с метапрограммированием

Рассмотрим следующий упрощенный шаблон метапрограммирующего кода, который реализует 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?

6

Решение

Код действителен. Visual C ++ правильно принимает это, а gcc неправильно отклоняет его (для полноты, Clang 3.1 также принимает код). В спецификации говорится, что (C ++ 11 7.1.6.4 [dcl.spec.auto] / 4):

auto Тип Спецификатор также может использоваться … при объявлении статического члена данных с скобки или равно-инициализатор который появляется внутри член-спецификация определения класса.

Ваш value является статическим членом данных. Оно имеет скобки или равно-инициализатор (это = Modulus<N, 360>::value часть декларации), и инициализатор появляется внутри член-спецификация определения класса (т. е. это то, что смертные могут назвать «встроенным инициализатором»).

1

Другие решения

Других решений пока нет …