[英]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.