简体   繁体   English

意外的模板与VC ++中的std :: void_t匹配

[英]Unexpected template matching with std::void_t in VC++

I have this code: https://ideone.com/dUkfjp 我有以下代码: https : //ideone.com/dUkfjp

#include <type_traits>

namespace details
{

template <typename T, typename U = T>
using equality_compare_ret_t = decltype(std::declval<T>() == std::declval<U>());

template <typename T, typename U = T>
using not_equality_compare_ret_t = decltype(std::declval<T>() != std::declval<U>());

};//end namespace details

template <typename, typename = std::void_t<>>
struct is_equality_comparable
    : std::false_type
{};

template <typename T>
struct is_equality_comparable<T,
    std::void_t<
        details::equality_compare_ret_t<std::remove_reference_t<T>>,
        details::not_equality_compare_ret_t<std::remove_reference_t<T>>
    >>
    : std::true_type
{};

template <typename T>
constexpr bool is_equality_comparable_v = is_equality_comparable<T>::value;


struct default_constuctible
{
    constexpr default_constuctible()
    {}
};

bool operator==(const default_constuctible&, const default_constuctible&)
{
    return true;
}
bool operator!=(const default_constuctible&, const default_constuctible&)
{
    return false;
}

static_assert(is_equality_comparable<default_constuctible>::value, "false");

Compiles with defaults on ideone C++14 (gcc 6.3) 在ideone C ++ 14(gcc 6.3)上使用默认值编译

The same code in godbolt.org compiles with clang 6.0.0 and gcc 8.1 and don't compiles with MSVC 19 2017 RTW. godbolt.org中的相同代码可以使用clang 6.0.0和gcc 8.1进行编译,而不能使用MSVC 19 2017 RTW进行编译。

Don't compiles because of the last line code: 由于最后一行代码,请勿编译:

static_assert(is_equality_comparable<default_constuctible>::value, "false");

In MSVC is_equality_comparable<default_constuctible>::value is evaluated as false and in clang/gcc is evaluted as true. 在MSVC中, is_equality_comparable<default_constuctible>::value的值为false,在clang / gcc中的值为true。 Same problem I have in MSVC 2017 community edition 15.7.3. 我在MSVC 2017社区版15.7.3中遇到相同的问题。

I don't understand why, bug in MSVC or in my code? 我不明白为什么,MSVC或代码中的错误?

fixed with 固定于

template <typename T>
using equality_compare_ret_t = decltype(std::declval<T>() == std::declval<T>());

template <typename T>
using not_equality_compare_ret_t = decltype(std::declval<T>() != std::declval<T>());

better solution (compiles in vc++ 15.7.3, doesn't compile in msvc 19 2017 rtw): 更好的解决方案(在vc ++ 15.7.3中编译,在msvc 19 2017 rtw中不编译):

#include <type_traits>

namespace details
{

template <typename T, typename U>
using equality_compare_with_ret_t = decltype(std::declval<T>() == std::declval<U>());

template <typename T, typename U>
using not_equality_compare_with_ret_t = decltype(std::declval<T>() != std::declval<U>());

template <typename T>
using equality_compare_ret_t = decltype(std::declval<T>() == std::declval<T>());

template <typename T>
using not_equality_compare_ret_t = decltype(std::declval<T>() != std::declval<T>());

};//end namespace details

template <typename, typename, typename = std::void_t<>>
struct is_equality_comparable_with
    : std::false_type
{};

template <typename T, typename U>
struct is_equality_comparable_with<T, U,
    std::void_t<
        details::equality_compare_with_ret_t<std::remove_reference_t<T>, std::remove_reference_t<U>>,
        details::not_equality_compare_with_ret_t<std::remove_reference_t<T>, std::remove_reference_t<U>>
    >>
    : std::true_type
{};

template <typename T, typename U>
constexpr bool is_equality_comparable_with_v = is_equality_comparable_with<T, U>::value;

template <typename, typename = std::void_t<>>
struct is_equality_comparable
    : std::false_type
{};

template <typename T>
struct is_equality_comparable<T,
    std::void_t<
        details::equality_compare_ret_t<std::remove_reference_t<T>>,
        details::not_equality_compare_ret_t<std::remove_reference_t<T>>
    >>
    : std::true_type
{};

template <typename T>
constexpr bool is_equality_comparable_v = is_equality_comparable<T>::value;


struct default_constuctible
{
    constexpr default_constuctible()
    {}
};

bool operator==(const default_constuctible&, const default_constuctible&)
{
    return true;
}
bool operator!=(const default_constuctible&, const default_constuctible&)
{
    return false;
}
bool operator==(const default_constuctible&, int)
{
    return true;
}
bool operator!=(const default_constuctible&, int)
{
    return false;
}

static_assert(is_equality_comparable<default_constuctible>::value, "false");
static_assert(is_equality_comparable_with<default_constuctible, int>::value, "false");
static_assert(!is_equality_comparable_with<default_constuctible, char*>::value, "false");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM