21

Possible Duplicate:
Can I declare variables of different types in the initialization of a for loop?

I'd like to have a for loop in c++ which constructs 2 different kinds of vector iterator in the initialisation.

Here is a rough idea of what I would like:

std::vector<double> dubVec;
std::vector<int> intVec;
double result = 0;

dubVec.push_back(3.14);
intVec.push_back(1);

typedef std::vector<int>::iterator intIter;
typedef std::vector<double>::iterator dubIter;

for (intIter i = intVec.begin(), dubIter j = dubVec.begin(); i != intVec.end(); ++i, ++j)
{
  result += (*i) * (*j);
}

Anyone know what is the standard to do in this situation? I can't just use a vector of double for the intVec because I'm looking for a general solution. [i.e. I might have some function f which takes int to double and then calculate f(*i) * (*j)]

Community
  • 1
  • 1
Derek
  • 818
  • 7
  • 11
  • 22

8 Answers8

37

You could declare a std::pair with first and second as the iterator types:

for (std::pair<intIter, dubIter> i(intVec.begin(), dubVec.begin());
     i.first != intVec.end() /* && i.second != dubVec.end() */;
     ++i.first, ++i.second)
{
    result += (*i.first) * (*i.second);
}
hmjd
  • 120,187
  • 20
  • 207
  • 252
  • This is a particularly clever solution I think. It also destroys the itrators at the end, which was part of my goal. I think what I was initially asking was whether it was possible to initialise 2 different types in a for loop (which is impossible). But this solution is really nice and unexpected. – Derek Mar 07 '12 at 14:24
  • As pointed out by Alecs in a comment below, this idea generalises to structs as seen here: http://stackoverflow.com/questions/8644707/can-i-declare-variables-of-different-types-in-the-initialization-of-a-for-loop – Derek Mar 07 '12 at 15:13
  • how do you take this one step futher, how do you have N? back to the struct, or is there a better thing to use? – kdubs Jul 16 '15 at 17:17
  • 1
    Consider changing the declaration to `auto i = std::make_pair(intVec.cbegin(), dubVec.cbegin())` – Jason Iverson Sep 18 '15 at 18:04
  • @kdubs - how about std::tuple http://en.cppreference.com/w/cpp/utility/tuple – newman911 Mar 09 '17 at 21:18
10

You can't declare variables of different types inside a for loop.

Just declare them outside:

intIter i = intVec.begin();
dubIter j = dubVec.begin();
for (; i != intVec.end(); ++i && ++j)
{
}
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
4

Check out the zip iterator. It does exactly what you want: parallel iterate over two or more sequences simultaneously. Using that, I'd write it as:

using namespace boost;

for (auto i=make_zip_iterator(make_tuple(dubVec.begin(), intVec.begin())),
          ie=make_zip_iterator(make_tuple(dubVec.end(), intVec.end()));
          i!=ie; ++i)
{
  // ...
}

Admittedly, this get's a little more complicated if you don't have support for auto or other type inference in your specific case, but it can still be quite nice with a typedef.

ltjax
  • 15,837
  • 3
  • 39
  • 62
3

For example

intIter i = intVec.begin();
dubIter j = dubVec.begin();
for (; i != intVec.end(); ++i && ++j)
{
  result += (*i) * (*j);
}

you can declare several var. only of the same type in the for. And are you sure with this part

++i && ++j

? I believe you want to write there

 ++i, ++j

So obviously you must read basics about for loop in C++

Alecs
  • 2,256
  • 8
  • 32
  • 45
  • sorry, I did mean ++i, ++j. however I was looking for a solution which also destructed the iterators at the end of the for loop, so they are not global variables. – Derek Mar 07 '12 at 14:19
  • @Derek if they are of different types there is no way to do that in the for loop.In your example you really don't need iterators, you just can use indexes, but I suppose that you showed us very simplified piece of code – Alecs Mar 07 '12 at 14:22
  • @Derek: If you really need to restrict their scope, then put the declarations and the loop into their own block. – Mike Seymour Mar 07 '12 at 14:23
  • @Derek actually, there is a hack, described [here in the accepted answer](http://stackoverflow.com/questions/8644707/can-i-declare-variables-of-different-types-in-the-initialization-of-a-for-loop), but it's really bad idea to use it in real life :-) – Alecs Mar 07 '12 at 14:25
  • I agree that the hack is probably not practical for nice readable code, but it is nice to know there is a way to do this. Out of curiosity, is it (much) quicker to use 2 separate iterators than to use an index in this case? – Derek Mar 07 '12 at 14:41
  • @Derek can't say for sure, it will be interesting to check it =) – Alecs Mar 07 '12 at 14:49
1

The easiest thing to do, at the expense of widening the scope of the iterators, would be to just hoist them up to the containing scope:

intIter i;
dubIter j;
for (i = intVec.begin(), j = dubVec.begin(); i != intVec.end(); ++i && ++j)
{
    result += (*i) * (*j);
}
Ernest Friedman-Hill
  • 80,601
  • 10
  • 150
  • 186
1

Don't overcomplicate things.

for( size_t i = 0; i < intVec.size(); ++i )
{
    result += intVec[i] * dubVec[i];
}
David
  • 27,652
  • 18
  • 89
  • 138
1

It seems you need an inner_product algorithm.

#include <vector>
#include <functional>
#include <numeric>
#include <iostream>

struct my_plus 
{
    double operator()(int i, double d)
    {
        return d + i;
    }
};

struct my_multiplies 
{
    double operator()(int i, double d)
    {
        return d * i;
    }
};

int main()
{
    std::vector<double> dubVec;
    std::vector<int> intVec;
    double result = 0;

    dubVec.push_back(3.14);
    intVec.push_back(1);

    result = std::inner_product(intVec.begin(), 
                                intVec.end(), 
                                dubVec.begin(),
                                0.0,
                                my_plus(),
                                my_multiplies());
    std::cout << result << std::endl;
}

I used my own functors, because I suspect the standard multiplies and plus expect both operands to be of similar type, but I might be wrong.

Anton Daneyko
  • 6,528
  • 5
  • 31
  • 59
0
intIter i;
dubIter j;
for (i = intVec.begin(), j = dubVec.begin(); i != intVec.end() && j != dubIter.end(); ++i, ++j)
{
    result += (*i) * (*j);
}
Igor Korkhov
  • 8,283
  • 1
  • 26
  • 31