Hi,

I've been learning about the std::copy function in the <algorithm> header and I'm stuck on this exercise that I gave my self.

Let's see the code snippet first:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;

ostream& operator<<(ostream& os, const int p_val)
{
    os.put( p_val*2);
    return os;
}

int main(/*const int argc,const char* const argv[]*/)
{
    std::vector<int> myVector = {34,54,43,2,7,87};

    std::copy(myVector.begin(), myVector.end(), ostream_iterator<int>(std::cout, " "));

    cin.get();
    return 0;
}

Basically what I'm trying to achieve is: I have a vector full of integers. I want to print the mutiply of 2 of these integers to std::cout using std::copy(). I learnt that I would have to overload operator<<(). But as you can see from my failed attempt above, I'm at a complete lost as to what I need to do insife operator<<().

Any help's much appreciated.

Cheers,
Ben

Edited 3 Years Ago by yxBen

For one, you cannot overload operators for basic types like int or double or whatever, there must be at least one non-primitive type in the operator's signature. In this case, it is OK on that aspect because ostream& os is a non-primitive type. However, there already exists an operator<< for the type int (or const int). It might be that your implementation (compiler) accepts it, depending on how it implemented the operator<< for built-in types, but you shouldn't do this, especially not if you are going to do something "weird" inside the operator (like print the value times 2).

One way to solve this problem would be to introduce a different type that just wraps the integer value. It's really just a placeholder to differentiate the types when the compiler does overload resolution. Here's what I mean:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

// create a type to hold a "doubled integer":
struct doubled_int {
  int value;

  // make it implicitly convertible (int -> doubled_int)
  doubled_int(int aValue) : value(aValue * 2) { };

  // make it implicitly convertible (doubled_int -> int)
  operator int() const { return value / 2; };
};

// overload the << operator for that wrapper type:
ostream& operator<<(ostream& os, doubled_int p_val) {
    return os << p_val.value;  // <-- print the doubled value.
}

int main()
{
    std::vector<int> myVector = {34,54,43,2,7,87};

    std::copy(myVector.begin(), myVector.end(), 
              ostream_iterator<doubled_int>(std::cout, " ")); // <-- notice '<doubled_int>'

    cin.get();
    return 0;
}

Of course, the above is pretty tedious and tricky, and not something I would recommend. It's just easier to do it the good old way, using a for loop:

int main()
{
    std::vector<int> myVector = {34,54,43,2,7,87};

    for(auto it = myVector.begin(); it != myVector.end(); ++it)
      std::cout << (*it) * 2 << " ";

    cin.get();
    return 0;
}

Or with range-based for-loop:

int main()
{
    std::vector<int> myVector = {34,54,43,2,7,87};

    for(auto i : myVector)
      std::cout << i * 2 << " ";

    cin.get();
    return 0;
}

But if you really must use one of the STL algorithms, you can just use a lambda expression and the std::for_each function:

int main()
{
    std::vector<int> myVector = {34,54,43,2,7,87};

    std::for_each(myVector.begin(), myVector.end(), [](int i) {
      std::cout << i * 2 << " ";
    } );

    cin.get();
    return 0;
}

Thanks Mikael for your very concise explaination. Now I know i shouldn't do that with primitive type as it creates an ambigous and the compiler does not like it. The idea was from a code snippet that i saw on one of reddit's daily programming challenge and it was used for a custom object. The code used std::copy() with std::cin to get some input and create some custom objects, and then process those objects all within an overloaded operator<<() and an operator>>() before finially throwing everything into an ostream_iterator(std::cout, " ").

So I thought I can dumb it down and use primitive types instead for practice :P

Here's a link to that coding challenge. [Link] And search for a submittion by the user Steve132.

Edited 3 Years Ago by yxBen

This article has been dead for over six months. Start a new discussion instead.