2013-05-27 8 views
12

Clang documentationはきちんとクラスまたは構造体は、ユーザー定義のデフォルトコンストラクタを持っていない継承されたデフォルトコンストラクタもユーザー定義ですか?

場合は、C++ あなたは この([dcl.init]のようにそれのconstのインスタンスを構築するデフォルトを許可しないことを説明して、P9)

次のコードはBaseため、このようなユーザー定義のデフォルトコンストラクタを持っていますが、g ++およびクランはDerivedが明示的にのすべてを継承しないにも関わらずDerivedのデフォルトコンストラクタは、ユーザが定義しているかどうか意見を異にのコンストラクタ(使用new C++11 inheriting constructors feature

#include <iostream> 

class Base 
{ 
public: 
    Base(): b_(0) {} // look! user-defined default constructor 
    void print() const { std::cout << b_ << "\n"; } 
private: 
    int b_; 
}; 

class Derived 
: 
    public Base 
{ 
    using Base::Base; // does this constitute a user-defined default constructor? 
}; 

int main() 
{ 
    Base const b; 
    b.print(); // 0 for g++ & CLang 

    Derived const d; 
    d.print(); // 0 for g++, Clang: "default initialization of an object of const type 'const Derived' requires a user-provided default constructor" 
} 

G ++ 4.8は、楽しく、このコードを受け入れ、しかしクラン3.3ありません。スタンダードは何を言いますか?

(例えばG ++ 4.7.2が以前に受け入れられたのに対し)Baseためのユーザ定義のデフォルトコンストラクタなし、どちらG ++ 4.8もクラン3.3 Base const b;を受け入れます。 g ++がルールを知っているとすれば、これはg ++がデフォルトのコンストラクタをユーザ定義としてDerivedとみなしていると考えられます。しかし、Clang 3.3はそうではないと考えています。

UPDATE:0/1引数のコンストラクタが継承されることはありませんことを@JesseGoodの回答に基づいて、私は

Base(int b = 0, void* = nullptr): b_(b) {} 

Baseコンストラクタを変更しようとしたが、それはクランのエラーを解決しません。

+0

あなたは正しく私は質問を誤解していた。 –

答えて

7

Clangが正しいです。

constのインスタンスについての関連通路が8.5p7からです:

プログラムは const修飾型Tのオブジェクトのデフォルトの初期化を要求した場合、Tはを持つクラス型でなければなりませんユーザー提供 デフォルトコンストラクタ。

Base(): b_(0) {}はユーザが提供しているため、Base const b;は問題ありません。

次の重要な部分は12.9p3ある:

継承 コンストラクタはパラメータ又は有する コピー/移動コンストラクタを持たないコンストラクタ以外 の候補セット内の各非テンプレートコンストラクタの

使用宣言が表示されている クラスに同じ署名を持つユーザー宣言されたコンストラクタがある場合を除いて、コンストラクタは同じコンストラクタの特性で暗黙的に宣言されます

ここで重要な部分は太字です。Base()はパラメータを持たないコンストラクタであるため、これはあなたのケースを除外していると私は信じています。つまり、Derivedには、ユーザーが指定したデフォルトのコンストラクタがありません(暗黙的に宣言されていますが)。

これは、基本クラスのデフォルト、コピーおよび移動コンストラクタがでないことを意味します。を継承します。

+0

+1あなたの答えに感謝します。 'Base'コンストラクタシグネチャを' Base(int b = 0、void * = nullptr):b_(b){} 'に変更すると、デフォルトコンストラクタは抑制されます。しかし、Clangは引き続き 'Derived'にエラーを与えます(g ++はそれを受け入れます)。 2つのデフォルトパラメータを持つコンストラクタも、パラメータを持たない継承されていないコンストラクタとしてカウントされますか? – TemplateRex

+2

@rhalbersma:はい、パラメータを持たない継承されていないctorとしてカウントされます。 'Base(int)'と 'Base(int、void *)'は継承されます。 (ただし、デフォルトの引数は継承されません)。 –

+0

ありがとう、私はあなたの答えを受け入れた。 – TemplateRex

関連する問題