我从https://en.cppreference.com/w/cpp/experimental/is_detected和Strange MSVC behaviour with std::experimental::is_detected都实施了std::experimental::is_detected
,以确保那里没有发生任何事情。
但是,从我看来,is_detected
似乎不适用于MSVC中的模板类,而Clang和GCC都可以。关于如何在MSVC中实现此功能的任何想法?
完整的复制代码也已结束 https://godbolt.org/z/wYe9M3
#include <type_traits>
// Type representing a missing type.
struct nonesuch
{
nonesuch() = delete;
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
void operator=(nonesuch const&) = delete;
};
#if 1 // from cppreference
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...> {
// Note that std::void_t is a C++17 feature
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>
using detected_t = typename detail::detector<nonesuch, void, Op, Args...>::type;
#else
namespace internal
{
template <typename V, typename D>
struct detect_impl
{
using value_t = V;
using type = D;
};
template <typename D, template <typename...> class Check, typename... Args>
auto detect_check(char)
-> detect_impl<std::false_type, D>;
template <typename D, template <typename...> class Check, typename... Args>
auto detect_check(int)
-> decltype(std::void_t<Check<Args...>>(),
detect_impl<std::true_type, Check<Args...>>{});
template <typename D, typename Void, template <typename...> class Check, typename... Args>
struct detect : decltype(detect_check<D, Check, Args...>(0)) {};
}
template <template< typename... > class Check, typename... Args>
using is_detected = typename internal::detect<nonesuch, void, Check, Args...>::value_t;
#endif
template <typename T, typename ...Ts>
using foo_bar = decltype(std::declval<T>().bar(std::declval<Ts>()...));
template <typename T>
using has_bar = is_detected<foo_bar, T, int>;
template<class T>
struct InterfaceImpl
{
static constexpr bool val = has_bar<T>::value;
protected:
int bar(int t) const {return 2;}
};
struct S : public InterfaceImpl<S> {};
struct S2 : public InterfaceImpl<S2>
{
int bar(int t) const {return 3;}
};
struct NonTemplate{};
struct NonTemplate2{
int bar(int t) const {return 3;}
};
int main(void)
{
S s;
static_assert(s.val == false);
S2 s2;
static_assert(s2.val == true);
static_assert(has_bar<NonTemplate>::value == false);
static_assert(has_bar<NonTemplate2>::value == true);
return 0;
}