Templates 编译时检查迭代器';的父类公共成员存在

Templates 编译时检查迭代器';的父类公共成员存在,templates,c++11,c++14,typetraits,c++17,c++20,Templates,C++11,C++14,Typetraits,C++17,C++20,我有一门课: class A { // ... public: std::string s; // ... } 和一个函数: void some_process(RandomIt first, RandomIt last) { static_assert(/* some check if *RandomIt has member with name `s` */, "Iterator must point to an object with

我有一门课:

class A
{
// ...
public:
    std::string s;
// ...
}
和一个函数:

void some_process(RandomIt first, RandomIt last)
{
    static_assert(/* some check if *RandomIt has member with name `s` */,
                  "Iterator must point to an object with member `s`");

    // further process using RandomIt and using *RandomIt.s
}
<如何在C++中实现此检查,直到C++ 17?< /p> ,

#包括
#包括
模板
结构具有_s:std::false_类型{};
模板
struct has_ss))>:std::true_type{};
模板
取消某些进程(先随机,后随机)
{
静态_断言(has_s{},
“迭代器必须指向成员为``的对象”;
}

:

#包括
#包括
模板
使用has_s_t=decltype(std::declval()->s);
模板
取消某些进程(先随机,后随机)
{
静态断言(std::是否检测到,
“迭代器必须指向成员为``的对象”;
}
,:

#包括
#包括
模板
结构具有_s:std::false_类型{};
模板
struct has_ss))>:std::true_type{};
模板
取消某些进程(先随机,后随机)
{
静态_断言(has_s{},
“迭代器必须指向成员为``的对象”;
}

:

#包括
#包括
模板
使用has_s_t=decltype(std::declval()->s);
模板
取消某些进程(先随机,后随机)
{
静态断言(std::是否检测到,
“迭代器必须指向成员为``的对象”;
}

另一个潜在的C++1z选项是概念。这里有一个简单的例子,这个概念本身可能没有什么用处,但是这个想法可以用来为你的情况做你需要的

template<typename T>
concept bool PointeeHasSMember = requires(T t) 
{
    t->s; // require t->s to be a valid expression
};

struct with_s 
{
    int s;
};

struct no_s {};

void some_process(PointeeHasSMember first, PointeeHasSMember last) {}

int main()
{
    with_s* with;
    no_s* without;

    some_process(with, with); // compiles
    some_process(without, without); // doesn't compile
}
模板
概念bool PointeeHasSMember=requires(T)
{
t->s;//要求t->s是有效的表达式
};
带_s的结构
{
int-s;
};
结构no_s{};
void some_进程(PointeeHasSMember优先,PointeeHasSMember最后){}
int main()
{
与_s*与;
没有,就没有;
某些_进程(with,with);//编译
某些_进程(没有,没有);//无法编译
}
在下,第二个调用在相关行
概念“PointeeHasSMember”未满足“未满足”时产生错误


使用概念的优点是实现简单,即使与检测习惯用法相比也是如此,并且概念成为函数模板的一部分。您可以灵活地嵌套需求、动态执行需求和重载概念。您的函数声明还清楚地说明了它的需求,而不是将其延迟到静态断言。

另一个潜在的C++1z选项是概念。这里有一个简单的例子,这个概念本身可能没有什么用处,但是这个想法可以用来为你的情况做你需要的

template<typename T>
concept bool PointeeHasSMember = requires(T t) 
{
    t->s; // require t->s to be a valid expression
};

struct with_s 
{
    int s;
};

struct no_s {};

void some_process(PointeeHasSMember first, PointeeHasSMember last) {}

int main()
{
    with_s* with;
    no_s* without;

    some_process(with, with); // compiles
    some_process(without, without); // doesn't compile
}
模板
概念bool PointeeHasSMember=requires(T)
{
t->s;//要求t->s是有效的表达式
};
带_s的结构
{
int-s;
};
结构no_s{};
void some_进程(PointeeHasSMember优先,PointeeHasSMember最后){}
int main()
{
与_s*与;
没有,就没有;
某些_进程(with,with);//编译
某些_进程(没有,没有);//无法编译
}
在下,第二个调用在相关行
概念“PointeeHasSMember”未满足“未满足”时产生错误

使用概念的优点是实现简单,即使与检测习惯用法相比也是如此,并且概念成为函数模板的一部分。您可以灵活地嵌套需求、动态执行需求和重载概念。您的函数声明还清楚地说明了它的需求,而不是将其延迟到静态断言

template<typename T>
concept bool PointeeHasSMember = requires(T t) 
{
    t->s; // require t->s to be a valid expression
};

struct with_s 
{
    int s;
};

struct no_s {};

void some_process(PointeeHasSMember first, PointeeHasSMember last) {}

int main()
{
    with_s* with;
    no_s* without;

    some_process(with, with); // compiles
    some_process(without, without); // doesn't compile
}