C++ 如何通过SFINAE测试结构是否包含特定成员
为了定义重载函数以将输入字符串解析为特定的数据类型,我如下所示:C++ 如何通过SFINAE测试结构是否包含特定成员,c++,c++17,visual-studio-2019,sfinae,C++,C++17,Visual Studio 2019,Sfinae,为了定义重载函数以将输入字符串解析为特定的数据类型,我如下所示: #include <type_traits> // /std:c++17 enabled template <class T> constexpr bool is_point_v = std::is_class_v<T> && !std::is_enum_v<T> && std::is_arithmetic_v<decltype(T::x
#include <type_traits>
// /std:c++17 enabled
template <class T>
constexpr bool is_point_v = std::is_class_v<T> && !std::is_enum_v<T>
&& std::is_arithmetic_v<decltype(T::x)>
&& std::is_arithmetic_v<decltype(T::y)>
&& (sizeof(T) == sizeof(T::y) + sizeof(T::y));
template <class T>
constexpr bool is_rect_v = std::is_class_v<T> && !std::is_enum_v<T>
&& std::is_arithmetic_v<decltype(T::left)>
&& std::is_arithmetic_v<decltype(T::top)>
&& std::is_arithmetic_v<decltype(T::right)>
&& std::is_arithmetic_v<decltype(T::bottom)>
&& (sizeof(T) == sizeof(T::left) + sizeof(T::top) + sizeof(T::right) + sizeof(T::bottom));
template<typename T>
struct Point {
std::enable_if_t<std::is_arithmetic_v<T>, T>
x {}, y {};
Point() noexcept {}
};
template<typename T>
struct Rect {
std::enable_if_t<std::is_arithmetic_v<T>, T>
left {}, top {}, right {}, bottom {};
Rect() noexcept {}
};
class DBParser
{
public:
template <typename T>
typename std::enable_if_t<std::is_arithmetic_v<T> || std::is_same_v<T, std::string> || std::is_same_v<T, std::string_view>, T>
get(const char* key, T defaultValue = {}) {
// ...
return defaultValue;
}
template <typename T>
typename std::enable_if_t<is_point_v<T>, T>
get(const char* key, T defaultValue = {}) {
// ...
return defaultValue;
}
template <typename T>
typename std::enable_if_t<is_rect_v<T>, T>
get(const char* key, T defaultValue = {}) {
// ...
return defaultValue;
}
};
int main()
{
DBParser db;
auto point1 = db.get<Point<int>>("point1", {});
auto point2 = db.get<Point<float>>("point2", {});
auto rect1 = db.get<Rect<int>>("rect1", {});
auto rect2 = db.get<Rect<float>>("rect2", {});
auto ret3 = db.get<int>("key3", {});
}
#包括
///std:c++17已启用
模板
constexpr bool is_point_v=std::is_class_v&!std::是_enum_v吗
&&std::是算法吗
&&std::是算法吗
&&(sizeof(T)==sizeof(T::y)+sizeof(T::y));
模板
constexpr bool is_rect_v=std::is_class_v&!std::是_enum_v吗
&&std::是算法吗
&&std::是算法吗
&&std::是算法吗
&&std::是算法吗
&&(sizeof(T)==sizeof(T::left)+sizeof(T::top)+sizeof(T::right)+sizeof(T::bottom));
模板
结构点{
std::如果启用,则启用
x{},y{};
Point()noexcept{}
};
模板
结构矩形{
std::如果启用,则启用
左{},上{},右{},下{};
Rect()noexcept{}
};
类DBParser
{
公众:
模板
typename std::启用\u如果\u t
get(const char*key,T defaultValue={}){
// ...
返回默认值;
}
模板
typename std::启用\u如果\u t
get(const char*key,T defaultValue={}){
// ...
返回默认值;
}
模板
typename std::启用\u如果\u t
get(const char*key,T defaultValue={}){
// ...
返回默认值;
}
};
int main()
{
dbdb;
auto point1=db.get(“point1”,{});
auto point2=db.get(“point2”,{});
auto rect1=db.get(“rect1”,{});
auto rect2=db.get(“rect2”,{});
auto-ret3=db.get(“key3”,{});
}
编译上面的代码时会出现错误。显然,我为函数“get”所做的SFINAE是不正确的,有点笨拙,但我无法理解
你能给我一些代码修复吗?如果C++17不能减少代码的冗长,我接受C++20
更新:
为了使问题更适合问题,我想更改标题并添加更多信息。
奇怪的是,如果我将struct的测试直接放在如下函数中:
template <class T>
std::enable_if_t < std::is_class_v<T> && !std::is_enum_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) { // Point
return defaultValue;
}
模板
std::如果
get(const char*key,T defaultValue){//Point
返回默认值;
}
它编译时没有错误。因此,我认为Nicol Bolas的假设可能是不正确的。我很确定这不是对类型进行SFINAE的方式(即:在成员上放置
enable\u if
)。我也很确定你所有的decltype(T::whatever)
东西都不起作用,因为这些都是成员指针,而不是成员本身。@Nicolas Bolas Hi Nicol,我更新了我的问题,在你的评论中提到了。