実際には、decltype
とレイトリターンバインディング機構のおかげで、C++ 11ではもっと楽になっています。
今、それがこのテストにメソッドを使用するだけで簡単です:あなたはその後、例えば、クラスでこれを使用することができます
// Culled by SFINAE if reserve does not exist or is not accessible
template <typename T>
constexpr auto has_reserve_method(T& t) -> decltype(t.reserve(0), bool()) {
return true;
}
// Used as fallback when SFINAE culls the template method
constexpr bool has_reserve_method(...) { return false; }
:
template <typename T, bool b>
struct Reserver {
static void apply(T& t, size_t n) { t.reserve(n); }
};
template <typename T>
struct Reserver <T, false> {
static void apply(T& t, size_t n) {}
};
をそして、あなたはそれを使用します。
template <typename T>
bool reserve(T& t, size_t n) {
Reserver<T, has_reserve_method(t)>::apply(t, n);
return has_reserve_method(t);
}
enable_if
の方法を選択することもできます。
template <typename T>
auto reserve(T& t, size_t n) -> typename std::enable_if<has_reserve_method(t), bool>::type {
t.reserve(n);
return true;
}
template <typename T>
auto reserve(T& t, size_t n) -> typename std::enable_if<not has_reserve_method(t), bool>::type {
return false;
}
これは実際には簡単ではないことに注意してください。一般的に、それははるかに簡単だだけSFINAEが存在する場合 - あなたはちょうどenable_if
1つの方法にしたいと任意のフォールバックを提供していない:置換が失敗した場合
template <typename T>
auto reserve(T& t, size_t n) -> decltype(t.reserve(n), void()) {
t.reserve(n);
}
、この方法は、可能な過負荷のリストから削除されます。
注:,
(カンマ演算子)の意味のおかげで、decltype
に複数の式を連鎖させることができ、最後の式だけが実際に型を決定します。複数の操作をチェックするのに便利です。私が指し示すしたい
template<typename> struct Void { typedef void type; };
template<typename T, typename Sfinae = void>
struct has_reserve: std::false_type {};
template<typename T>
struct has_reserve<
T
, typename Void<
decltype(std::declval<T&>().reserve(0))
>::type
>: std::true_type {};
:
C++ 11では、C++ 03に必要なこのラウンドアバウトの方法の代わりに、 "式のためのsfinae"を使用することができます。 –
@ JohannesSchaub-litb解決を求める!私は、このような例の違いを見たいと思っています。 – stinky472