繁体   English   中英

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

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

我有以下代码: 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");

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

godbolt.org中的相同代码可以使用clang 6.0.0和gcc 8.1进行编译,而不能使用MSVC 19 2017 RTW进行编译。

由于最后一行代码,请勿编译:

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

在MSVC中, is_equality_comparable<default_constuctible>::value的值为false,在clang / gcc中的值为true。 我在MSVC 2017社区版15.7.3中遇到相同的问题。

我不明白为什么,MSVC或代码中的错误?

固定于

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>());

更好的解决方案(在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