8

次のスニペットがあります

#include <type_traits>
#include <boost/type_traits.hpp>

class C { C() { } };

int main()
{
   static_assert(!boost::has_trivial_default_constructor<C>::value, "Constructible");
   static_assert(!std::is_default_constructible<C>::value, "Constructible");
}

条件は等しくありませんが、最初の条件は正常に機能し、2 番目の構成ではエラーが発生します。そのコンストラクターはプライベートです。Compiler gcc 4.7... では、これは gcc のバグですか、それとも標準で定義されていますか?

http://liveworkspace.org/code/NDQyMD $5

わかった。この条件は実際には等しくないため、次のようなものを使用できます

#include <type_traits>
#include <boost/type_traits.hpp>

class C { private: C() noexcept(false) { } };

int main()
{
   static_assert(!boost::has_nothrow_constructor<C>::value, "Constructible");
   static_assert(!std::is_nothrow_constructible<C>::value, "Constructible");
}

http://liveworkspace.org/code/NDQyMD $24

とにかく、タイプは実際にはデフォルトで構築可能ではない/非スロー構築可能ではないため、 static_assert が失敗しないことを知っています。質問: 静的アサートによるものではなく、コンパイル エラーが発生するのはなぜですか?

4

1 に答える 1

5

コンパイラのバグのようです。次の SFINAE の例を見てみましょう (同様の実装がg++type_traitsヘッダーで使用されています) 。

#include <type_traits>

class Private
{
    Private()
    {

    }
};

class Delete
{
    Delete() = delete;
};

struct is_default_constructible_impl
{
    template<typename T, typename = decltype(T())>
    static std::true_type test(int);

    template<typename>
    static std::false_type test(...);
};

template <class T>
struct is_default_constructible: decltype(is_default_constructible_impl::test<T>(0))
{

};

int main()
{
    static_assert(is_default_constructible<Private>::value, "Private is not constructible");
    static_assert(is_default_constructible<Delete>::value, "Delete is not constructible");
}

Deleteクラスには削除されたコンストラクターが 1 つしかないため、2 番目の assert は期待どおりに機能します。型を推測することはできません。しかし、コンパイラが の型を推測しようとするとPrivate()、エラーが発生します: Private::Private() is private. したがって、プライベートコンストラクターを持つ2つのクラスがありますが、そのうちの1つはエラーを返し、2番目はエラーを返しません。この動作は間違っていると思いますが、標準で確認できません。

PS すべての提示されたコードは、エラーなしで clang によってコンパイルされます。

于 2012-12-25T15:27:20.197 に答える