2017-08-22 17 views
15

を無視します。 GCCは、しかし、私は私はデフォルトの初期化子を使用しようとしていると思わせるエラーメッセージが表示できます:(ASTExprのみまさにこのコンストラクタを提供します)私はこのようなパブリックコンストラクタでusing ASTExpr::ASTExpr;を交換した場合継承コンストラクタは、私がこのように定義されたクラスがあり、クラスの初期化

error: no matching function for call to ‘EmojicodeCompiler::Type::Type()’

ASTConcatenateLiteral(const SourcePosition &p) : ASTExpr(p) {} 

すべて正常に動作します。 cppreference.comによると

The inherited constructors are equivalent to user-defined constructors with an empty body and with a member initializer list consisting of a single nested-name-specifier, which forwards all of its arguments to the base class constructor.

なぜ継承されたコンストラクタが動作しませんか?継承されたコンストラクタがユーザ定義のコンストラクタのように動作する場合は、type_の値を使用する必要があります。どのコンパイラが標準に従っていますか?

+3

これはg ++ 7.2でうまくコンパイルされます。 – Holt

+0

@Holt Sheesh。以前のバージョンでのみ失敗した場合でも、問題を再現することはできませんでした。 – hvd

+0

@Holt 6.2.0で試しました。しかし、その場合、私はGCCのバージョン要件をもう一度突き詰めなければならないでしょう... – idmean

答えて

15

Clangが正しいです。 inherited constructorが使用されている場合、既定の既定のコンストラクターを使用して派生クラスのオブジェクトを初期化するかのように初期化を続行する必要があります。default member initializersを使用する必要があります。

(強調鉱山)

If overload resolution selects one of the inherited constructors when initializing an object of such derived class, then the Base subobject from which the constructor was inherited is initialized using the inherited constructor, and all other bases and members of Derived are initialized as if by the defaulted default constructor (default member initializers are used if provided, otherwise default initialization takes place).

ここstandardからの例です:d.yがデフォルトのメンバー初期化子で初期化されていることを

struct B1 { 
    B1(int, ...) { } 
}; 

struct B2 { 
    B2(double) { } 
}; 

int get(); 

struct D1 : B1 { 
    using B1::B1;  // inherits B1(int, ...) 
    int x; 
    int y = get(); 
}; 

void test() { 
    D1 d(2, 3, 4); // OK: B1 is initialized by calling B1(2, 3, 4), 
        // then d.x is default-initialized (no initialization is performed), 
        // then d.y is initialized by calling get() 
    D1 e;    // error: D1 has a deleted default constructor 
} 

注意。

12

これは、GCC 7.2で修正された、コンパイラのバグPR67054としてGCC開発者によって考えられました。

Their minimal exampleはオンラインのコンパイラはGCCと打ち鳴らすは契約になっていることを確認するために使用することができます

struct A 
{ 
    A(int) {} 
}; 

struct C 
{ 
    C(int) {} 
}; 

struct B : A 
{ 
    using A::A; 
    C c = 42; 
}; 

int main() 
{ 
    B b = 24; 
} 

です。

GCC 7.1では、私が知る限り、間違ったコードは生成されないことに注意してください。コンパイラはデフォルトコンストラクタを必要としましたが、そのデフォルトコンストラクタは決して呼び出されませんでした。したがって、古いバージョンのGCCでは、デフォルトコンストラクタの宣言が提供されますが、定義は提供されません。おそらく、それを使用しようとする試みを拒否する属性(標準C++ではない)を使用することさえあるでしょう:

struct C 
{ 
#ifdef GCC_WORKAROUND_PR67054 
    C() __attribute__((__error__("No."))); 
#endif 
    C(int) {} 
};