是否可以迭代结构或类中的所有元素?
例如,如果我有三个不同类型的元素的结构:
struct A {
classA a;
classB b;
classC c;
};
然后我需要一些迭代器,这样方法next()会给我一个值 下一个元素。问题是,如您所见,值具有不同的类型。
答案 0 :(得分:4)
不,不是用这种语言。
你可以通过从公共库中派生类来实现它,然后实现自己的迭代器,以便在遍历迭代器时返回指向每个项的指针。
或者将项目放在std::vector
中并使用它来提供迭代。
答案 1 :(得分:4)
不,C ++中没有任何反映,(但是,有一天会出现关于静态反射的杂音)。
无论如何,有一种方法可以解决这个问题 - 首先,你需要一个(临时的)元组来引用你的数据成员。
然后你需要一个构造“迭代”元组,例如:
void applyToAll() { }
template <typename Lambda, typename... Lambdas>
void applyToAll(Lambda&& closure, Lambdas&&... closures) {
std::forward<Lambda>(closure)();
applyToAll(std::forward<Lambdas>(closures)...);
}
// use your favourite sequence-making trick
template <unsigned... Is>
struct _Sequence {
typedef _Sequence<Is...> type;
};
template <unsigned Max, unsigned... Is>
struct _MakeSequence : _MakeSequence<Max - 1, Max - 1, Is...> { };
template <unsigned... Is>
struct _MakeSequence<0, Is...> : _Sequence<Is...> { };
template <typename Tuple, typename Functor, unsigned... Is>
void _foreachElemInTuple(_Sequence<Is...>, Tuple&& t, Functor&& f) {
applyToAll(
[&]{ std::forward<Functor>(f)(std::get<Is>(std::forward<Tuple>(t))); }...
);
}
template <typename Tuple, typename Functor>
void foreachElemInTuple(Tuple&& t, Functor&& f) {
_foreachElemInTuple(
_MakeSequence<std::tuple_size<
typename std::decay<Tuple>::type>::value>(),
std::forward<Tuple>(t), std::forward<Functor>(f)
);
}
然后你可以致电foreachElemInTuple(yourTuple, some_adapter())
。
您的适配器将如下所示:
struct some_adapter {
template <typename... Args>
// A little bit of C++14, you can also just -> decltype the thing
decltype(auto) operator()(Args&& ... args) const {
return doStuff(std::forward<Args>(args)...);
}
};
答案 2 :(得分:0)
正如其他人所说,你不能直接迭代a的数据成员
类。但是,当然也可以间接地做到这一点
您可以访问要迭代的每个数据成员。这个想法
根据ScarletAmaranth的解决方案,在essense中,迭代std::tuple
对那些数据成员的引用。
以下程序显示了如何使用std::forward_as_tuple
获取这样的元组,
和另一种通过编译时递归进行迭代的方法
辅助器具。
#include <tuple>
/* You want to be able do something with the values of the members of an `A`
in turn.
*/
struct A
{
char ch;
int i;
double d;
// May also have members of class type. It doesn't matter
};
/* 1) Provide yourself with the means of creating a sequence that contains
references to the data members of a given `A`
*/
std::tuple<char const &, int const &, double const &> get_A_vals(A const & a)
{
return std::forward_as_tuple(a.ch,a.i,a.d);
}
/* 2) Provide yourself with a means of applying some operation, `Func`,
to each element of an `std::tuple`
*/
template<size_t I = 0, typename Func, typename ...Ts>
typename std::enable_if<I == sizeof...(Ts)>::type
for_each_in_tuple(std::tuple<Ts...> const &, Func) {}
template<size_t I = 0, typename Func, typename ...Ts>
typename std::enable_if<I < sizeof...(Ts)>::type
for_each_in_tuple(std::tuple<Ts...> const & tpl, Func func)
{
func(std::get<I>(tpl));
for_each_in_tuple<I + 1>(tpl,func);
}
/* 3) Combine 1) and 2) to apply `Func` over the members of an `A`
*/
template<typename Func>
void for_each_in_A(A const & a, Func func)
{
for_each_in_tuple(get_A_vals(a),func);
}
// Testing...
#include <iostream>
// A specimen operation: just prints its argument
struct printer
{
template<typename T>
void operator () (T && t)
{
std::cout << t << std::endl;
}
};
int main()
{
A a{'a',1,2.0};
for_each_in_A(a,printer());
return 0;
}
// EOF
程序输出:
a
1
2
如果您可以控制您需要的成员的结构或类
迭代,您可以考虑放弃它们是否切实可行
并在任何地方使用相应的std::tuple
。
使用gcc 4.8.2和clang 3.3,-std=c++11
构建的代码。