Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何通过SFINAE测试结构是否包含特定成员_C++_C++17_Visual Studio 2019_Sfinae - Fatal编程技术网

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,我更新了我的问题,在你的评论中提到了。