2

完全な (ない) 動作例:

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 ‘&amp;’ operand
constexpr.cpp:9:16: error: could not convert template argument ‘(const s*)(& s_objs)’ to ‘const s*’

最後の 2 行は 3 回繰り返されます。理由は何ですか? gcc 4.7.3 で私のコードを使用するための回避策はありますか?

4

1 に答える 1

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;
}

C++ 11を有効にせずにgcc 4.8.1でも動作しています。

したがって、回避策は次のとおりです。

変化する

constexpr const s s_objs[] = ...;

extern const s s_objs[] = ...;

ライブの例はこちら.

変数を静的クラス メンバーにしたい場合は、外部リンケージを持つように指定する必要があります。

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

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

これにより、4.8 ではなくgcc 4.7 で警告が表示されます。また、 Rise4Fun ではコンパイルされません。したがって、これが純粋な標準なのか、コンパイラのバグなのかはわかりません。

于 2014-02-06T15:00:08.093 に答える