我有以下代码: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或代码中的错误?
答案 0 :(得分:0)
固定为
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>());
答案 1 :(得分:0)
更好的解决方案(在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");