使用元编程实现Auto + static类内恒定初始化

Tem*_*Rex 6 c++ metaprogramming static-members auto c++11

考虑以下简化的模板元编程代码,该代码实现了一个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;
}
Run Code Online (Sandbox Code Playgroud)

Ideone上的输出

使用Visual C++ 2010 Express,我可以这样做static auto const = Modulus<N, 360>::value,但是使用MinGW gcc 4.7.2(Nuwen 发行版)或Ideone(gcc 4.5.1),我必须明确地将类型表示为static int const value = Modulus<N, 360>::value或者我必须使用auto完整的模块化表达式作为static auto const value = N % 360;.

问题:根据新的C++ 11标准,哪个编译器是正确的?

Jam*_*lis 1

该代码有效。Visual C++ 接受它是正确的,而 gcc 拒绝它是错误的(为了完整性,Clang 3.1 也接受该代码)。规范指出 (C++11 7.1.6.4[dcl.spec.auto]/4):

类型auto 说明符还可以用于...声明带有大括号或等于初始化程序的静态数据成员,该初始化程序出现在类定义的成员规范中。

value是静态数据成员。它有一个大括号或等于初始化器(即= Modulus<N, 360>::value声明的一部分),并且初始化器出现在类定义的成员规范中(即,人们可能称之为“内联初始化器”)。