1

I have m ints and n floats and I want to iterate over them in one loop. In order to do so, I can think of two possible ways but I don't know if they are actually feasible:

  1. Ideally I want to store the m+n numbers in one array (e.g. in one std::vector), is there a way (a container, or by means of polymorphism) that I could do this?

  2. If I must store the ints and floats in two arrays, is there (or how to write) an iterator that can iterate the two arrays in on loop?

Any idea is welcome!

5
  • You can use any to store them but you'd need to have a marker variable to know where to start reading ints and where to start reading floats, just placing them in two arrays would be simpler. Commented Aug 16, 2016 at 10:49
  • 2
    Why do you want to iterate them in one loop? Commented Aug 16, 2016 at 10:49
  • 2
    I want to iterate them in one loop because it would make my original program more concise since it does the same thing regardless of the data type Commented Aug 16, 2016 at 10:55
  • 1
    It seems you need a template function: template <typename T> void iterate_array(T *first, T *last);, then you just call the function twice with different arguments: iterate_array(int_arr, int_arr + size); iterate_array(float_arr, float_arr + size); Commented Aug 16, 2016 at 10:59
  • assuming you have the same number of each you can use std::pair Commented Aug 16, 2016 at 11:08

4 Answers 4

2

It seems a template function might be a good solution:

  1. it preserves the semantics of "doing the same for both containers of floats and containers of ints", without creating an artificial container of floats/ints for the sake of saving a few lines of code
  2. from a performance perspective there will be no difference with a hand coded loop iterating over both arrays if you enable compiler optimisations -O3
  3. it will work for other types (e.g. double, int64_t, int32_t etc.)

It would look like this:

template<typename T>
void processData(std::vector<T> data) {
   for (auto& d : data) {
     // do some processing
   }
} 

you would call it with:

processData(std::vector<float>{1.2, 2.5, 3.5, 4.5});
processData(std::vector<int>{1, 2, 3, 4});

see a working example here

Sign up to request clarification or add additional context in comments.

Comments

2

There are several options, with all their different advantages and disadvantages:

  1. Use two std::vector, one for int the other for float, and iterate them in separate loops. If the loop body is non-trivial, put it into a templated function, so you don't have to duplicate the code.

  2. Use an std::vector of boost::any, which can store both floats and ints. When acquiring the value, you have to "cast" it into the right type. Again you might want to put any logic into a templated function to avoid code duplication. Since the boost::any cast to the actual type involves type checking, this solution has not optimal performance. On the other hand it comes close to the behavior of runtime-typed languages like Python.

  3. Especially if you have more then just two types: Use a boost::fusion::map of the type (float and int) to the vector of the type. You can iterate the map with boost::fusion::foreach, which will call a templated function and pass the vectors to it. This way you get essentially the first solution, but this time it scales more easily for many data types.

Since C++ is statically typed, there is no way to have a single container containing both floats and ints without boost::any. Exception: if the number of entries is fixed at compile time, a boost::mpl::vector could help you.

Edit: If you want code examples, give use more information which way you want to go...

Comments

1

You may factorize your code differently, for example:

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;
};

And then, usage is similar to

MyData myData = /**/;

myData.run([](auto e){ std::cout << e << " "; });

Comments

0

Either create a struct and use that as your array:

struct my_compund_type {
  int integer;
  float very_narrow_and_possibly_I_meant_double_float;
};

std::vector<my_compund_type> array;

Your other option is to do a for loop that only iterates over the indexes, and access both arrays as necessary.

1 Comment

This only works if m == n. Especially if the two values logically are not pairs (i.e. they don't belong together), it would be a very misleading solution...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.