我有一个班级:
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 ++ 17到C ++实现此检查?
答案 0 :(得分:4)
+-----+---------------+---------------+
| id | team_A | team_B |
+-----+---------------+---------------+
| 1 | Barcelona | Real Madrid |
+-----+---------------+---------------+
| 2 | Milan | Inter |
+-----+---------------+---------------+
#include <type_traits>
#include <utility>
template <typename T, typename = void>
struct has_s : std::false_type {};
template <typename T>
struct has_s<T, decltype(void(std::declval<T>()->s))> : std::true_type {};
template <typename RandomIt>
void some_process(RandomIt first, RandomIt last)
{
static_assert(has_s<RandomIt>{},
"Iterator must point to an object with member `s`");
}
答案 1 :(得分:2)
另一个潜在的C ++ 1z选项是Concepts。这是一个概念的简单示例,它本身可能没有用,但这个想法可以用来制作你所需要的东西。
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
}
在latest GCC下,第二次调用会产生相关行concept 'PointeeHasSMember<no_s*>' was not satisfied' was not satisfied
的错误。
使用概念的优点是简单的实现,甚至与检测习语相比,并且概念成为功能模板的一部分。您可以灵活地嵌套需求,执行动态要求以及对概念进行重载。您的函数声明也明确说明了它的要求,而不是将其延迟到静态断言。