2016-12-02 14 views
4

のstd ::配列<>とstd :: IS_ARRAY <>は、両方のC++ 11で導入されたので、これはコンパイルに失敗したことを非常に奇妙なようだ:なぜstd :: is_arrayはstd :: arrayに対してfalseを返しますか?

#include <array> 
#include <type_traits> 

static_assert(std::is_array<std::array<int,2>>::value); 

がいるかどうかを確認するための簡単な方法はあります何かが配列で、T[N]std::array<T,N>の両方の可能性を含んでいますか?それは残念ながらstd::arrayのための専門を提供していません

template<class T> 
struct is_array : std::false_type {}; 

template<class T> 
struct is_array<T[]> : std::true_type {}; 

template<class T, std::size_t N> 
struct is_array<T[N]> : std::true_type {}; 

+2

'std :: array'は単純に配列ではありません。彼らは 'std :: array_wrapper'や' std :: better_array'のようなものよりも便利な名前だから、ちょうどそれを呼びました。 – user2357112

+0

@ user2357112: 'is_array <>'の意味は 'array <>'を定義したのと同じ言語の同じバージョンによって決定されていたので、 "配列は配列ではない"という概念は不合理に思われます? –

+1

スマートポインタは 'is_pointer'も渡しません。 'std :: is_array'は特殊な' std :: array'を使うとそれほど役に立たないでしょうし、 'std :: array'を実際の配列にすることは、まず' std :: array'を作成する全体の点を打ち負かします。名前があなたに混乱させないようにしてください。 – user2357112

答えて

1

Cppreferenceは、この可能な実装を提供します。あなたがこれを行うことにより、独自のを行うことができます。

template<class T> 
struct is_array : std::is_array<T> {}; 
template<class T, std::size_t N> 
struct is_array<std::array<T, N>> : std::true_type {}; 
+0

回避策は、インクルード注文に応じて第三者のライブラリインヘッダコードを破損する可能性があります –

+0

@MMあなたは何をお勧めしますか? 'std'の中​​に特殊化を直接作りますか? – 0x499602D2

+2

'std :: is_array'は' std :: array'ではなくCスタイルの配列を参照することを理解することをお勧めします。もしそれらの両方にマッチする特性を望むなら、独自の形質を作ります –

4

ISO/IEC 14882:2011、20.9.4.1条、表47はこれを言う:

  • は、テンプレート:テンプレートの構造体IS_ARRAY。

  • 条件:Tが配列型である(3.9.2)は、既知または未知の程度の

  • コメント:クラステンプレート配列(23.3.2)は、アレイ型ではありません。

したがって、アサーションは失敗するはずです。

@ 0x499602D2の提案通りにis_arrayを特化することはできますが、そうした場合は、標準化された機能の意味を変更しないでください。

+0

参考になりました。 C配列とC配列を区別するために 'std :: is_class <>'を使用するコードを作成できませんでしたか? –

+0

@JohnZwinckはい、できます。私は、標準的な作家がこの方法でもっと便利だと思ったと思います。 – harmic

+0

@harmicあなたの最後の段落は、不正な形式のプログラムで、診断は必要ありません。 'std'名前空間内の特性クラスの特殊化は、標準で文書化されているような特性クラスの公理に違反してはならない。 – Yakk

1

std::is_arrayは、T[]またはT[N]のようなタイプの場合にのみ真となるように定義されています。 std::arrayは含まれていません。

std::is_arraytrue_typeに変更するか、標準でstd::arrayを指定することはできません。あなたのプログラムを不正な形にし、診断は必要ありません。 std内のタイプを特化する場合、その結果は標準と一致していなければなりません。標準はここでは具体的です。 (また、stdの中の他のテンプレートについては、違法であることが非常に疑わしい)。

自分is_array形質を作成することができます。

namespace notstd { 
    template<class T> 
    struct is_array:std::is_array<T>{}; 
    template<class T, std::size_t N> 
    struct is_array<std::array<T,N>>:std::true_type{}; 
    // optional: 
    template<class T> 
    struct is_array<T const>:is_array<T>{}; 
    template<class T> 
    struct is_array<T volatile>:is_array<T>{}; 
    template<class T> 
    struct is_array<T volatile const>:is_array<T>{}; 
} 

その後、Cスタイルの配列またはC++ std::arrayのいずれかを検出するために、他の場所でnotstd::is_array<T>を使用しています。

関連する問題