4

ここでの元のタイトルは 、VS2005 C++ の SFINAE バグの回避策でした。

これは、TR1 に存在する is_pod テンプレート クラスに相当するものを作成するための SFINAE の暫定的な使用です (VS2005 にはまだ TR1 はありません)。テンプレート パラメーターが POD 型 (プリミティブ型とそれらで作成された構造体を含む) の場合はメンバーを true にし、そうでない場合 (非自明なコンストラクターなど) は false にする必要があります。

template <typename T> class is_pod
{
  public:

    typedef char Yes;
    typedef struct {char a[2];} No;

    template <typename C> static Yes test(int)
    {
      union {T validPodType;} u;
    }
    template <typename C> static No test(...)
    {
    }
    enum {value = (sizeof(test<T>(0)) == sizeof(Yes))};
};

class NonPOD
{
  public:
    NonPod(const NonPod &);
    virtual ~NonPOD();
};

int main()
{
  bool a = is_pod<char>::value;
  bool b = is_pod<NonPOD>::value;
  if (a) 
    printf("char is POD\n");
  if (b)
    printf("NonPOD is POD ?!?!?\n");
  return 0;
}

問題は、VS 2005 に TR1 がないだけでなく、上記の共用体 (テンプレート パラメーターが POD でない場合は有効ではない) を気にしないため、a と b の両方が true と評価されることです。


以下に投稿された回答に感謝します。それら (およびコード) を注意深く読んだ後、私がやろうとしていたことは本当に間違ったアプローチであることに気付きました。アイデアは、SFINAE の動作をテンプレートmust_be_podへの適応と組み合わせることでした (本Imperfect C++で見つけましたが、別の場所でも見つけることができます)。実際、これには SFINAE の非常に特殊なルール セットが必要になりますが、これは明らかに標準で定義されているものではありません。結局のところ、これは実際には VS のバグではありません。

4

3 に答える 3

4

あなたのアプローチの最大の問題は、ここで SFINAE を実行しないことです。SFINAE は、ここではパラメーターの型と戻り値の型にのみ適用されます。

ただし、標準のすべての SFINAE シチュエーションのうち、どれもあなたのシチュエーションには当てはまりません。彼らです

  • void、参照、関数、または無効なサイズの配列
  • 型ではない型メンバー
  • 参照へのポインタ、参照への参照、void への参照
  • 非クラス型のメンバーへのポインター
  • テンプレート値パラメーターの無効な変換
  • void 型の引数を持つ関数型
  • const/volatile 関数型

それがおそらく、Boost のドキュメントに次のような記述がある理由です。

コンパイラからの何らかの (まだ指定されていない) 助けがなければ、ispod はクラスまたは構造体が POD であることを報告しません。最適ではない可能性がある場合でも、これは常に安全です。現在 (2005 年 5 月)、MWCW 9 と Visual C++ 8 のみが必要なコンパイラー_intrinsics を備えています。

于 2009-02-11T00:14:54.303 に答える
2

これはVS2008でも機能しませんが、あなたもそれを知っていると思います. SFINAE は、テンプレート パラメーターのテンプレート引数を推測するためのものです。別の型と互換性のない型を作成することはできますが (つまり、union は非 POD を使用できません)、型のコンストラクター性を明らかにするものの型を実際に推測することはできません。

実際、VS 2008 はコンパイラ サポートを使用してトレイトを実装していstd::tr1::type_traitsます。

于 2009-02-11T00:06:31.953 に答える