鑑於2種T
和U
我想檢測是否有可能那些對象(即之間的呼叫operator *
是有可能寫t * u
其中t
是T
型和u
是U
型)檢測操作人員是否存在,在C調用++(考慮static_asserts)
我使用c++ detection idiom的,但因爲它沒有在我的編譯器可我實現了我自己這樣
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 I有這樣的幫手:
template <typename T, typename U>
using multiply = decltype(std::declval<T>() * std::declval<U>());
,並檢測它是否是可調用我打電話
bool can_multiply = is_detected_v<multiply, T, U>
這幾乎是罰款,例如該打印1,0預期
std::cout << is_detected_v<multiply, int, int> << std::endl;
std::cout << is_detected_v<multiply, std::vector<int>, std::vector<int>> << std::endl;
但現在我有課
template<typename T>
class A {
};
template<typename T>
A<T> operator*(const A<T>&, const A<T>&) {
static_assert(!std::is_same<bool, T>::value);
return A<T>();
}
這裏A<bool>
不能A<bool>
相乘,但我的代碼檢測,它可能
std::cout << is_detected_v<multiply, A<bool>, A<bool>> << std::endl; // 1
A<bool>() * A<bool>(); // does't compile
所以,我的問題是,如何修復我的代碼無法檢測方法時,他們static_asserted了呢?我想我可以代替static_assert
一些SFINAE,但我不想(因爲我沒有獲得再說static_asserts有更好的錯誤信息)。
解釋爲什麼可能會幫助(SFINAE支票必須重載期間進行;迫使每一個編譯器來編譯每個函數,並確定是否有任何非法的代碼之前,確定哪些超載要求編譯器作者都希望能努力,並可能導致在令人驚訝的行爲中(因爲你的'T *'代碼包含一個導致錯誤代碼2級嵌套深的錯誤),所以'我更喜歡void *'over'T *'。 SFINAE檢查是一種妥協,即使在那裏,MSVC也會對他們造成嚴重影響。 – Yakk