MSVC中的std :: is_detected不适用于模板

时间:2019-02-05 18:58:58

标签: c++ templates template-meta-programming crtp

我从https://en.cppreference.com/w/cpp/experimental/is_detectedStrange 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;
}

0 个答案:

没有答案