gcc 4.7有时无法使用指针模板参数

时间:2014-02-06 09:21:08

标签: c++ templates gcc c++11 compiler-bug

完成(非)工作示例:

struct s { int i; };

template<const s* _arr>
class struct_array
{
public:
    static constexpr auto arr = _arr[0]; // works
    template<int >
    struct inner // line 9, without this struct, it works
    {    
    };
};

constexpr const s s_objs[] = {{ 42 }};

int main()
{
    struct_array<s_objs> t_obj;
    return 0;
}

编译如下:

g++ -std=c++11 -Wall constexpr.cpp -o constexpr

我使用ideone的gcc 4.8.1运行程序,但4.7.3将此打印给我:

constexpr.cpp: In instantiation of ‘class struct_array<((const s*)(& s_objs))>’:
constexpr.cpp:18:30:   required from here
constexpr.cpp:9:16: error: lvalue required as unary ‘&’ operand
constexpr.cpp:9:16: error: could not convert template argument ‘(const s*)(& s_objs)’ to ‘const s*’

最后两行重复3次。是什么原因,是否有任何解决方法在gcc 4.7.3上使用我的代码?

1 个答案:

答案 0 :(得分:1)

这对我来说似乎是一个编译错误。

我在gcc 4.1.2(codepad)上试过你的例子,你必须明确地注意到变量有外部链接(const暗示内部链接,除非另有说明,以下代码是C ++ 03) :

struct s { int i; };

template<const s* _arr>
class struct_array
{
public:
    static const s arr;
    template<int >
    struct inner
    {    
    };
};

template<const s* _arr>
const s struct_array<_arr>::arr = _arr[0];

// Notice the 'extern'
extern const s s_objs[] = {{ 42 }};

int main()
{
    struct_array<s_objs> t_obj;
    return 0;
}

我也在gcc 4.8.1 without启用了C ++ 11。

所以,解决方法是:

变化

constexpr const s s_objs[] = ...;

extern const s s_objs[] = ...;

Live example here

如果您希望变量是静态类成员,则必须将其指定为具有外部链接:

struct data
{
    static const s s_objs[1];
};

extern const s data::s_objs[1] = {{ 42 }};

这给了我一个warning on gcc 4.7,而不是4.8。它也是doesn't compile on Rise4Fun。所以,我不确定这是纯标准还是其中一个编译器中的错误。