28

この質問に答えた後、Boost ライブラリでテンプレートを見つけようとis_completeしていましたが、Boost.TypeTraits にそのようなテンプレートがないことに気付きました。Boostライブラリにそのようなテンプレートがないのはなぜですか? それはどのように見えるべきですか?

//! Check whether type complete
template<typename T>
struct is_complete
{   
  static const bool value = ( sizeof(T) > 0 );
};

...

// so I could use it in such a way
BOOST_STATIC_ASSERT( boost::is_complete<T>::value );

sizeof不完全な型に適用することは違法であるため、上記のコードは正しくありません。良い解決策は何ですか?この場合、どういうわけかSFINAEを適用することは可能ですか?


まあ、この問題はODR 規則に違反しない限り一般的に解決できませんでしたが、私にとって有効なプラットフォーム固有の解決策があります。

4

9 に答える 9

17

Alexey Malistov によって与えられた回答は、MSVC でわずかな変更を加えて使用できます。

namespace 
{
    template<class T, int discriminator>
    struct is_complete {  
      static T & getT();   
      static char (& pass(T))[2]; 
      static char pass(...);   
      static const bool value = sizeof(pass(getT()))==2;
    };
}
#define IS_COMPLETE(X) is_complete<X,__COUNTER__>::value

残念ながら、__COUNTER__定義済みマクロは標準の一部ではないため、すべてのコンパイラで機能するとは限りません。

于 2009-12-24T01:14:41.857 に答える
5

is_complete残念ながら、そのような型特性を実装することはできません。@Alexey によって提供された実装は、G++ 4.4.2 および G++ 4.5.0 でコンパイルに失敗します。

エラー: 「static char (& is_complete::pass(T))[2] [with T = Foo]」の引数 1 を初期化しています</p>

私の Mac では、G++ 4.0.1 を使用してis_complete<Foo>::value、どこstruct Foo;が不完全かを評価するとtrue、コンパイラ エラーよりもさらに悪い結果が得られます。

T翻訳単位に応じて、同じプログラム内で完全な場合と不完全な場合がありますが、常に同じタイプです。結果として、上でコメントしたように、is_complete<T>も常に同じタイプです。

したがって、ODRis_complete<T>を尊重する場合、使用される場所に応じて異なる値を評価することはできません。そうしないと、is_complete<T>ODR が禁止する定義が異なることになります。

編集: 受け入れられた答えとして、マクロが使用されるたびに、マクロを使用__COUNTER__して異なるis_complete<T, int>型をインスタンス化するソリューションをハッキングしましたIS_COMPLETE。しかし、gcc ではそもそも SFINAE を動作させることができませんでした。

于 2009-12-23T15:44:24.687 に答える
2

不完全な型の sizeof が 0 になることを保証するものを標準で見つけることができません。ただし、T がある時点で不完全であるが、その翻訳単位で後で完了する場合、T へのすべての参照が参照する必要があります。同じタイプに - 私が読んだように、テンプレートが呼び出された場所で T が不完全であっても、その翻訳単位のどこかで T が完了していれば、完了したと言う必要があります。

于 2009-10-26T14:35:30.457 に答える