2016-09-12 9 views
7

std::is_constructiblestd::is_destructibleを評価すると、ClangとGCCはfriend宣言を守らないようです。 is_constructible `に関して友人宣言による影響を受けていないis_constructibleとis_destructible

cppreference.com says:

アクセスチェックがTとargs内の型のいずれかに無関係文脈からいるかのように実行されます。変数定義の直後のコンテキストの妥当性のみが考慮されます。

(サイトは、アクセスチェックでどのようにis_destructible取引を説明しますが、アクセス修飾子しないは、一般的にis_destructibleの動作に影響を与えないので、私はそれがis_constructibleと同じように動作することを期待したい。)

ローカル変数のインスタンス化によって証明されるように即時コンテキストでコンストラクタとデストラクタをご確認のは、利用可能なのでしたがって、それは、このコードはないコンパイルする必要がありますように私には思える:

class Private 
{ 
    Private() {} 
    ~Private() {} 

    friend class Friend; 
}; 

class Friend 
{ 
    public: 
     Friend() 
     { 
      // Both of these should fire, but they do not. 
      static_assert(
       !std::is_constructible<Private>::value, 
       "the constructor is public"); 
      static_assert(
       !std::is_destructible<Private>::value, 
       "the destructor is public"); 
      // There is no error here. 
      Private p; 
     } 
}; 

...しかし、Coliru compiles it without error(GCCまたはClangを使用)。

コンパイラのバグ(または少なくとも不適合)、またはcppreference.comが標準を欺いている、あるいは私がcppreference.comの記述を誤解していますか?

+0

これは基本的に標準からの直接の引用です(カップルワードを変更して)。また、それは「即時の文脈」が意味するものではない。 –

+0

@ T.C。私は "直接的な文脈"が標準語で何を意味するのか分かりませんが、 'is_constructible'の結果はオブジェクトが*の次のコード行*に構築できるかどうかについては何も教えてくれません。 –

+1

代わりに、同じ型( 'is_constructible ')*は、使用する場所によって異なる基本クラス*を持ちます。 –

答えて

2

これは

アクセスチェックがTArgsにおけるタイプのいずれかとは無関係のコンテキストからかのように実行されるまさにあります。

となります。 「Tの友人」は定義上「Tとは無関係」ではありません。

"immediate context"は、いずれの場合でも、文は、is_constructibleの使用ではなく、仮説的な変数定義の直接的なコンテキストについて話しています。

is_constructibleをコンテキスト依存にすることは賢明です。つまり、同じタイプのis_constructible<T, Args...>は、異なるコンテキストで異なる基本クラスを持つことを意味します。

関連する問題