Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ADL using std types fails to find operator

Tags:

c++

c++14

The following code fails to compile

namespace A {
using C = std::vector<std::string>;
std::ostream& operator << (std::ostream& lhs, const C& rhs) {
    lhs << 5;
    return lhs;
}
}
int main()
{
    A::C f;
    std::cout << f;
    return 0;
}

with the error

Error   C2679   binary '<<': no operator found which takes a right-hand operand of type 'A::C' (or there is no acceptable conversion)   

Obviously it cant find the << operator presumably due to considering C to be a class from the std namespace. Is there some way to ensure the compiler finds this operator or otherwise work around the problem?

like image 891
Bomaz Avatar asked Apr 06 '17 11:04

Bomaz


1 Answers

A::C is just a type alias, and aliases are transparent. They don't "remember" where they came from. When we do argument-dependent lookup and figure out what the associated namespaces are, we only consider the associated namespaces of the types - not the alias that got us there. You can't just add associated namespaces to existing types. The specific associated namespace of f (which is of type std::vector<std::string>) is std, which doesn't have an operator<< associated with it. Since there's no operator<< found using ordinary lookup, nor is there one found using ADL, the call fails.

Now, I said you can't just add associated namespaces to existing types. But you can of course just create new types:

namespace A {
    struct C : std::vector<std::string> { };
}

or:

namespace A {
    // template parameters are also considered for associated namespaces
    struct S : std::string { };
    using C = std::vector<S>;
}
like image 176
Barry Avatar answered Nov 10 '22 20:11

Barry