考えると2種類T
とU
を検出することt
はタイプT
のですt * u
を記述することが可能であり、 u
は、私がc++ detection idiomを使用しています)タイプU
のが、私はそれはすなわち(オブジェクトにそれらの間<code>operator *</code>を呼び出すことが可能ですかどうかを検出したい(static_assertsを考慮して)++演算子はCに存在し、呼び出し可能かどうか
ですが、それは私のコンパイラではまだ利用できませんので、私はこの
struct nonesuch {
nonesuch() = delete;
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
void operator=(nonesuch const&) = delete;
};
namespace detail {
template <class Default, class AlwaysVoid, template<class...> class Op, class... Args>
struct detector {
using value_t = std::false_type;
using type = Default;
};
template <class Default, template<class...> class Op, class... Args>
struct detector<Default, std::void_t<Op<Args...>>, Op, Args...> {
using value_t = std::true_type;
using type = Op<Args...>;
};
} // namespace detail
template <template<class...> class Op, class... Args>
using is_detected = typename detail::detector<nonesuch, void, Op, Args...>::value_t;
template< template<class...> class Op, class... Args >
constexpr bool is_detected_v = is_detected<Op, Args...>::value;
ないようにそれを自分自身を実装しました私は、このようなヘルパー持っW:
template <typename T, typename U>
using multiply = decltype(std::declval<T>() * std::declval<U>());
をし、それは私が今
std::cout << is_detected_v<multiply, int, int> << std::endl;
std::cout << is_detected_v<multiply, std::vector<int>, std::vector<int>> << std::endl;
しかし、予想通りそれは、例えば、これは1を出力し、ほとんど大丈夫です0
bool can_multiply = is_detected_v<multiply, T, U>
を呼び出す呼び出し可能なのかどうかを検出します私はクラスを持っています
ここA<bool>
はA<bool>
で乗算することはできませんが、私のコードは、それは彼らがstatic_assertedたときに私の質問は、どのような方法を検出しないように自分のコードを修正している、
std::cout << is_detected_v<multiply, A<bool>, A<bool>> << std::endl; // 1
A<bool>() * A<bool>(); // does't compile
だから、可能だということを検出しますか?私はstatic_assert
をいくつかのsfinaeに置き換えることができると思いますが、(私はアクセス権がなく、static_assertsにはより良いエラーメッセージがあるので)したくありません。
なぜ、役立つのか説明する(SFINAEのチェックは、オーバーロード解決中に行う必要があります。すべてのコンパイラーにすべての関数をコンパイルして、どのオーバーロードを呼び出すかを判断する前にすべての関数をコンパイルして判定します( 'T *'コードには深いネストされたコード2のレベルでエラーにつながるバグが含まれているので、私は 'T * 'より' void * 'を選んでいました)。 SFINAEの小切手は妥協であり、そこにさえMSVCはそれらに落ち着きます。 – Yakk