8

decltypeSFINAEでの使用は簡単enable_ifではないようです。私は3つの異なる方法でgo使用法を書いてみました。enable_ifそれらはすべてコンパイラエラーで失敗しました(GCCでは文字通り「エラー:'thing'は'foo'のメンバーではありません」とインスタンス化コンテキストです)。

#include <type_traits>

struct foo {
  enum { has_thing = false };
};

struct bar {
  enum { has_thing = true };
  static int thing() { return 0; }
};

template <typename T>
struct Test {
  /*auto go(typename std::enable_if<T::has_thing, int>::type=0) 
  -> decltype(T::thing()) {
    return T::thing();
  }*/

  /*typename std::enable_if<T::has_thing, decltype(T::thing())>::type go() {
    return T::thing();
  }*/

  template <bool B=T::has_thing, typename std::enable_if<B, int>::type = 0>
  auto go() -> decltype(T::thing()) {
     return T::thing();
  }
};

int main() {
  Test<bar> b;
  Test<foo> f;
}

私は問題が何であるかを見ることができます-関数を除外する機会をdecltype得る前に起こる必要があります。enable_if残っている問題は、どのように回避して同様の動作を得るかです。has_thingで使用するトレイトを書くことに頼らずにこれを行うための簡単で一般的な方法は ありenable_ifますか?

G++4.7とclang++3.0の両方でテストされています。

4

2 に答える 2

6

SFINAEは、goメソッドがテンプレートメソッドの場合に機能します。

template <typename T>
struct Test {
  template <class U = T>
  auto go() -> decltype(U::thing()) {
     return T::thing();
  }
};

値を使用することもできますがhas_thing、上記の例ではSFINAEが処理するため、使用する必要はありません。

template <class U = T, typename std::enable_if<U::has_thing, int>::type = 0>
auto go() -> decltype(U::thing()) {
   return T::thing();
} 

それで:

int main() {
  Test<bar> b;
  Test<foo> f;

  b.go(); // Works!
  f.go(); // Fails!
}
于 2012-07-02T11:55:41.827 に答える
0

もちろん、SFINAEは機能しません。このgo関数はテンプレートではないため、SFINAEを適用することはできません。それ以外は問題なく動作するはずです(実際にはフラグdecltypeは必要ありません)。has_thing

例えば。これは正常に機能します(そして他のオーバーロードとうまく機能します):

template <class U>
auto go(Test<U> t)
  -> decltype(U::thing()) {
  return U::thing();
}
于 2012-07-02T11:51:12.373 に答える