Overloading of << operator using iterator as

2019-09-17 23:14发布

问题:

I`d like to print enum values as text and use for it overloading. Suppose I have the following code:

#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <unordered_set>

enum enm{
    One,
    Two
};

class Complex{
public:
friend std::ostream& operator<<(std::ostream& out, std::unordered_multiset<int>::const_iterator i){
    switch (*i){
        case One:{
            return out<<"One";
        }
        case Two:{
            return out << "Two";
        }
    }
}
void func(std::unordered_multiset<int> _v);
};

void Complex:: func(std::unordered_multiset<int> _v){
    _v.insert(One);
    _v.insert(Two);
    for (std::unordered_multiset<int>::const_iterator i(_v.begin()), end(_v.end()); i != end; ++i){
        std::cout <<"Num: " << *i <<std::endl; //need to get here "One", "Two" instead of 0, 1
    }
}

int main(){
    Complex c;
    std::unordered_multiset<int> ms;
    c.func(ms);
    return 0;   
}

The problem is this variant doesn`t work. So, I get 0, 1 instead of One, Two. Have no ideas how to do it properly. Thank you for help!

回答1:

I'm assuming you changed i to *i in order for your program to compile. In order to print the iterator you must do i, but this fails with a compiler error.

The problem is that the insertion operator is defined as a friend within the class on its first declaration, so the lookup to find this operator can only depend on namespaces and classes associated with the argument types, a lookup referred to as ADL or Koenig lookup.

Since std::ostream and unordered_multiset::const_iterator are not asscoiated with Complex (see ADL#Details), lookup fails to find the insertion operator.

The solution is to declare the function outside of the class so that normal unqualified lookup for the operator takes place:

std::ostream& operator<<(std::ostream&, std::unordered_multiset<int>::const_iterator);
class Complex { .. };

I would recommend however that you define the operator outside of the class, as it doesn't seem to need to access private/protected members of Complex (part of the purpose of befriending entities).