混乱を避けるために編集してください:は2 つの引数を受け入れ
decltype
ません。回答を参照してください。
T
次の 2 つの構造体を使用して、コンパイル時に型のメンバー関数の存在を確認できます。
// Non-templated helper struct:
struct _test_has_foo {
template<class T>
static auto test(T* p) -> decltype(p->foo(), std::true_type());
template<class>
static auto test(...) -> std::false_type;
};
// Templated actual struct:
template<class T>
struct has_foo : decltype(_test_has_foo::test<T>(0))
{};
メンバー関数の存在を確認するときに SFINAE を使用するという考えがあるため、有効でない場合に備えて、 を返す のp->foo()
省略記号バージョンのみが定義されています。それ以外の場合、最初のメソッドは for に定義され、 を返します。実際の「切り替え」は、 によって返される型を継承する 2 番目のクラスで発生します。これは、そのようなさまざまなアプローチと比較して、巧妙で「軽量」に見えます。test
std::false_type
T*
std::true_type
test
is_same
with two 引数はdecltype
、式の型を取得するだけだと思っていたので、最初は驚きました。上記のコードを見たとき、「式をコンパイルして、常に秒の型を返すようにしてください。式がコンパイルに失敗した場合は失敗します」のようなものだと思いました (したがって、この特殊化を非表示にします; SFINAE)。
しかし:
次に、このメソッドを使用して、 type に依存する限り、「有効な式である」チェッカーを作成できると考えましたT
。例:
...
template<class T>
static auto test(T* p) -> decltype(bar(*p), std::true_type());
...
これは、最初のパラメーターとしてa を受け入れるように定義されているstd::true_type
場合にのみ(または変換可能である場合など)、つまり、型が定義されているコンテキストで書かれている場合はコンパイルされると思いました。 .bar
T
T
bar(*p)
p
T*
ただし、上記の変更は常にに評価されstd::false_type
ます。どうしてこれなの?複雑な別のコードで修正したくありません。期待どおりに機能しない理由を知りたいだけです。明らかにdecltype
、2 つの引数を使用すると、私が思っていたものとは異なる動作をします。ドキュメントが見つかりませんでした。どこでも 1 つの表現だけで説明されています。