std :: is_constructibleがプライベートコンストラクターに矛盾した値を返す


13

std::is_constructibleがプライベートコンストラクターを処理するルールは何ですか?次のコードがあるとします:

#include <iostream>

class Class {
private:
    Class() { }
};

template <typename T>
class Test {
public:
    static void test() {
        std::cout
            //<< std::is_constructible<Class>::value
            << std::is_constructible<T>::value
            << std::endl;
    }
};

int main() {
    Test<Class>::test();
}

これは0ideone)を出力しTます。つまり、デフォルトでは構築できません。

コメント行のコメントを外すと、出力されます11ideone)。そのため、突然Tデフォルトで構築可能になりました。

私は両方の結果をサポートする理由を見つけることができましたが、コメント行を含めると2番目の結果がどのように変わるかわかりません。これはどういうわけかUBを呼び出していますか?これはコンパイラのバグですか?それともstd::is_constructible本当に矛盾していますか?


1
GCCバグのように見え、clang 9が出力00
Yksisarvinen

1
私のマシンでc ++ 17 g ++ 9.2.1 / g ++-10.0を使用してコンパイルし、std :: is_constructible <...> :: valueをis_constructible_v <...>で置き換えるときに気づいたもう1つの奇妙な考えは、結果は00に変更
mutableVoid

1
@mutableVoid確かに-そして、::valueバージョンはそれより前に来るものの出力を変更することができるようです:godbolt.org/z/zCy5xUコメントされた行のコメントを外すと、すべてgccで1:sになります。
Ted Lyngmo

1
それを修正する別の方法:godbolt.org/z/EKaP3rなので、基本的にこれはある種の評価順序バグです。
マレックR

2
@mutableVoid trueになるために関数テンプレートをインスタンス化する必要さえありません。この例では戻りますfalseが、関数テンプレートのコメントが解除されていると、突然戻りますtruegodbolt.org/z/zqxdk2
Ted Lyngmo

回答:


3

std::is_constructiblefalseコンストラクタにアクセスできないため、このシナリオではが返されます。

質問の下で指摘したように、質問で説明されている動作は、GCC / libstdc ++のバグが原因です。バグはここ報告されており、Bugzillaによると、かなり前から解決されていないテンプレート関数のクラスのアクセス制御バグが原因ではない場合に関連しています。2つのバグ間の関係は、最初に2つのバグ間の関連を検出したと思われるJonathan WakelyのBugzillaコメントから取得されます。

これは、コンストラクターをプライベートにするのではなく削除すると、GCCでのこのシナリオの動作が正しくなることからも示唆されます。

class Class {
    Class() = delete;
};

これはプリントアウト0して00、それぞれ。これは正しい出力です(clangプライベートコンストラクターを使用したシナリオでも正しくレポートされます)。

テンプレート化された構造体の関数内ではアクセスチェックが機能せず、アクセスできない場合はコンストラクターにアクセスできると報告されるため、これは行でコメントするときに 観察された動作の変化を説明できます。トレイトが次の行で再度チェックされる場合、または完全に異なる場所でチェックされる場合(ここでは)、すでにインスタンス化されているため、間違った答えが返されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.