10

文字列リテラルを使用してコンストラクターでメンバーを初期化する次の例std::array <char, N>は、GCC 4.8 ではコンパイルされませんが、Clang 3.4 を使用してコンパイルされます。

#include <iostream>
#include <array>

struct A {
  std::array<char, 4> x; 
  A(std::array<char, 4> arr) : x(arr) {}
};


int main() {
    // works with Clang 3.4, error in GCC 4.8.
    // It should be the equivalent of "A a ({'b','u','g','\0'});"
    A a ({"bug"});
    for (std::size_t i = 0; i < a.x.size(); ++i)
        std::cout << a.x[i] << '\n';

    return 0;
}

第一印象では、GCC のバグのように見えます。std::array<char, N>文字列リテラルで直接初期化できるので、コンパイルする必要があると思います。例えば:

std::array<char, 4> test = {"bug"}; //works

これについて標準が何を述べているかを知りたいと思います。

4

1 に答える 1

2

はい、あなたのコードは有効です。これは gcc のバグです。

バグを示す簡単なプログラムを次に示します (関数を返すだけでバグを示すことができるため、に置き換えstd::array<char, 4>て削除しました (これにより、コンストラクターのオーバーロードを心配する必要がないため、分析が簡単になります)。SA

struct S { char c[4]; };
S f() { return {"xxx"}; }

ここでは、 braced -init-listからコピー初期化(8.5p15) されたタイプの宛先オブジェクトがSあるため、オブジェクトはリスト初期化(8.5p17b1) されます。 は集合体 (8.5.1p1) であるため、集合体の初期化が実行されます (8.5.4p3b1)。集合体の初期化では、メンバーは対応する初期化句(8.5.1p2)からコピー初期化されます。ここで、型の宛先オブジェクトと文字列リテラルの初期化子を使用して 8.5p17 に戻ります。したがって、8.5p17b3 は 8.5.2 を参照し、配列の要素は文字列の連続する文字 (8.5.2p1) によって初期化されます。 {"xxx"}Sc "xxx"char[4]"xxx"char

gcc はS s = {"xxx"};、さまざまな形式のコピー初期化および直接初期化を中断しながら、コピー初期化に問題がないことに注意してください。引数の受け渡し (コンストラクターを含む)、関数の戻り値、およびベースとメンバーの初期化:

struct S { char c[4]; };
S f() { return {"xxx"}; }
void g(S) { g({"xxx"}); }
auto p = new S({"xxx"});
struct T { S s; T(): s({"xxx"}) {} };
struct U: S { U(): S({"xxx"}) {} };
S s({"xxx"});

最後のものは、これがバグ 43453に関連している可能性があることを示しているため、特に興味深いものです。

于 2014-02-04T16:53:03.857 に答える