C ++遍历不同类型的数组
c++ iterate over arrays of different types
我有 m 个整数和 n 个浮点数,我想在一个循环中迭代它们。为了做到这一点,我想到了两种可能的方法,但我不知道它们是否真的可行:
理想情况下,我想将 m+n 个数字存储在一个数组中(例如,在一个 std::vector 中),有没有一种方法(容器,或通过多态性)我可以这样做吗?
如果我必须将整数和浮点数存储在两个数组中,是否有(或如何编写)可以在循环中迭代这两个数组的迭代器?
欢迎任何想法!
要么创建一个结构并将其用作数组:
struct my_compund_type {
int integer;
float very_narrow_and_possibly_I_meant_double_float;
};
std::vector<my_compund_type> array;
您的另一个选择是执行一个仅遍历索引的 for 循环,并根据需要访问两个数组。
模板函数似乎是一个很好的解决方案:
- 它保留了 "doing the same for both containers of floats and containers of ints" 的语义,而没有为 floats/ints 创建一个人工的 容器节省几行代码
- 从性能的角度来看,如果您启用编译器优化,则与手动编码循环迭代两个数组没有区别
-O3
- 它适用于其他类型(例如
double
、int64_t
、int32_t
等)
看起来像这样:
template<typename T>
void processData(std::vector<T> data) {
for (auto& d : data) {
// do some processing
}
}
你会这样称呼它:
processData(std::vector<float>{1.2, 2.5, 3.5, 4.5});
processData(std::vector<int>{1, 2, 3, 4});
有多种选择,各有优缺点:
使用两个 std::vector,一个用于 int,另一个用于 float,并在单独的循环中迭代它们。如果循环体很重要,将其放入模板函数中,这样就不必重复代码。
使用boost::any的std::vector,既可以存储float也可以存储int。获取值时,你必须"cast"将其转换为正确的类型。同样,您可能希望将任何逻辑放入模板函数中以避免代码重复。由于 boost::any 转换为实际类型涉及类型检查,因此该解决方案的性能不是最佳的。另一方面,它接近运行时类型语言的行为,如 Python.
特别是如果你有不止两种类型:使用类型(float 和 int)的 boost::fusion::map 到类型的向量。您可以使用 boost::fusion::foreach 迭代地图,这将调用模板化函数并将向量传递给它。这样你基本上得到了第一个解决方案,但这次它更容易扩展到许多数据类型。
由于 C++ 是静态类型的,因此没有 boost::any 就无法让一个容器同时包含浮点数和整数。例外:如果条目数在编译时是固定的,boost::mpl::vector 可以帮助你。
编辑:如果您想要代码示例,请提供更多信息以供您使用...
您可以对代码进行不同的因式分解,例如:
struct MyData {
template <typename FUNC>
void run(FUNC func) {
for (auto& i : ints) {
func(i);
}
for (auto& f : floats) {
func(f);
}
}
std::vector<int> ints;
std::vector<floats> floats;
};
然后,用法类似
MyData myData = /**/;
myData.run([](auto e){ std::cout << e << " "; });
我有 m 个整数和 n 个浮点数,我想在一个循环中迭代它们。为了做到这一点,我想到了两种可能的方法,但我不知道它们是否真的可行:
理想情况下,我想将 m+n 个数字存储在一个数组中(例如,在一个 std::vector 中),有没有一种方法(容器,或通过多态性)我可以这样做吗?
如果我必须将整数和浮点数存储在两个数组中,是否有(或如何编写)可以在循环中迭代这两个数组的迭代器?
欢迎任何想法!
要么创建一个结构并将其用作数组:
struct my_compund_type {
int integer;
float very_narrow_and_possibly_I_meant_double_float;
};
std::vector<my_compund_type> array;
您的另一个选择是执行一个仅遍历索引的 for 循环,并根据需要访问两个数组。
模板函数似乎是一个很好的解决方案:
- 它保留了 "doing the same for both containers of floats and containers of ints" 的语义,而没有为 floats/ints 创建一个人工的 容器节省几行代码
- 从性能的角度来看,如果您启用编译器优化,则与手动编码循环迭代两个数组没有区别
-O3
- 它适用于其他类型(例如
double
、int64_t
、int32_t
等)
看起来像这样:
template<typename T>
void processData(std::vector<T> data) {
for (auto& d : data) {
// do some processing
}
}
你会这样称呼它:
processData(std::vector<float>{1.2, 2.5, 3.5, 4.5});
processData(std::vector<int>{1, 2, 3, 4});
有多种选择,各有优缺点:
使用两个 std::vector,一个用于 int,另一个用于 float,并在单独的循环中迭代它们。如果循环体很重要,将其放入模板函数中,这样就不必重复代码。
使用boost::any的std::vector,既可以存储float也可以存储int。获取值时,你必须"cast"将其转换为正确的类型。同样,您可能希望将任何逻辑放入模板函数中以避免代码重复。由于 boost::any 转换为实际类型涉及类型检查,因此该解决方案的性能不是最佳的。另一方面,它接近运行时类型语言的行为,如 Python.
特别是如果你有不止两种类型:使用类型(float 和 int)的 boost::fusion::map 到类型的向量。您可以使用 boost::fusion::foreach 迭代地图,这将调用模板化函数并将向量传递给它。这样你基本上得到了第一个解决方案,但这次它更容易扩展到许多数据类型。
由于 C++ 是静态类型的,因此没有 boost::any 就无法让一个容器同时包含浮点数和整数。例外:如果条目数在编译时是固定的,boost::mpl::vector 可以帮助你。
编辑:如果您想要代码示例,请提供更多信息以供您使用...
您可以对代码进行不同的因式分解,例如:
struct MyData {
template <typename FUNC>
void run(FUNC func) {
for (auto& i : ints) {
func(i);
}
for (auto& f : floats) {
func(f);
}
}
std::vector<int> ints;
std::vector<floats> floats;
};
然后,用法类似
MyData myData = /**/;
myData.run([](auto e){ std::cout << e << " "; });