我有几个重载函数,如下所示:
template<typename T>
struct Point {
std::enable_if_t<std::is_arithmetic_v<T>, T>
x, y;
};
// These are two functions accepting only Point<> type.
template <typename T>
std::enable_if_t < std::is_class_v<T>
&& std::is_arithmetic_v<decltype(T::x)>
&& std::is_arithmetic_v<decltype(T::y)>
&& sizeof(T) == sizeof(decltype(T::x)) + sizeof(decltype(T::y)), T>
get(const char* key, T defaultValue)
{
// do something ..
return defaultValue;
}
template <typename T>
void set(const char* key, std::enable_if_t < std::is_class_v<T>
&& std::is_arithmetic_v<decltype(T::x)>
&& std::is_arithmetic_v<decltype(T::y)>
&& sizeof(T) == sizeof(decltype(T::x)) + sizeof(decltype(T::y)), T> value)
{
// do something ..
}
template <typename T>
std::enable_if_t <std::is_arithmetic_v<T>, T>
get(const char* key, T defaultValue)
{
return defaultValue;
}
template <typename T>
std::enable_if_t <std::is_enum_v<T>, T>
get(const char* key, T defaultValue)
{
return defaultValue;
}
// There are others overloading get<>(), set<>() for other types.
// Then call them
auto pod1 = get<int>(key, {});// OK
auto pod2 = get<float>(key, {});// OK
auto enm = get<SomeEnum>(key, {});// OK
auto pt1 = get<Point<int>>(key, {}); // OK
auto pt2 = get<Point<std::string>>(key, {}); // failed - correctly.
到目前为止,代码运行良好,但看起来相当冗长。
我想要的是避免在 get/set 函数中重复检查 Point<> 类型的最巧妙方法是什么?。
我已经尝试过这些,但它们不起作用:
template <typename T>
using is_point_t = std::enable_if_t <
std::is_class_v<T>
&& std::is_arithmetic_v<decltype(T::x)>
&& std::is_arithmetic_v<decltype(T::y)>
&& (sizeof(T) == sizeof(decltype(T::x)) + sizeof(decltype(T::y))), T>;
template <typename T>
is_point_t<T>
get(const char* key, T defaultValue)
{
// do something
return defaultValue;
}
template <typename T>
void set(const char* key, is_point_t<T> value)
{
// do something
}
// Or even like this, it also fails
template <typename T>
inline constexpr bool is_point_v = std::is_class_v<T>
&& std::is_arithmetic_v<decltype(T::x)>
&& std::is_arithmetic_v<decltype(T::y)>
&& (sizeof(T) == sizeof(decltype(T::x)) + sizeof(decltype(T::y)));
template <typename T>
std::enable_if_t <is_point_v<T>, T>
get(const char* key, T defaultValue)
{
// do something
return defaultValue;
}
template <typename T>
void set(const char* key,
std::enable_if_t <is_point_v<T>, T> value)
{
// do something
}
MSVC 2019 错误 C1001:编译器中发生内部错误。 错误 C1001:要解决此问题,请尝试简化或更改上面列出的位置附近的程序。
它不起作用,因为如果类型
T
不包含成员属性x
、y
,编译会失败。要创建 is_point
类型特征(如果满足上述所有条件则为真),有必要利用 SFINAE。
namespace detail {
template <typename, bool = true>
struct is_point
: std::false_type {};
template <typename T>
struct is_point<T, std::is_class_v<T>
&& std::is_arithmetic_v<decltype(T::x)>
&& std::is_arithmetic_v<decltype(T::y)>
&& (sizeof(T) == sizeof(decltype(T::x)) + sizeof(decltype(T::y)))>
: std::true_type {};
}
template <typename T>
struct is_point
: detail::is_point<T> {};
template <typename T>
inline constexpr bool is_point_v = is_point<T>::value;