I am having trouble with the two-phase look-up as specified by the standard and (correctly) implemented by clang in connection with an overload of operator<<
for std::ostream
and std::vector
.
Consider a very generic template function which shifts its argument into a stream (really useful only with recursion, but the simple example is enough to trigger the problem):
// generic.h
template<typename Stream, typename Arg>
void shift(Stream& s, Arg& arg) { s << arg; }
This generic.h may be used throughout a project. Then in some other file, we want to output a std::vector
, so we define an overload
// vector.h
#include <iostream>
#include <vector>
std::ostream& operator<<(std::ostream& s, std::vector<int> const& v) {
for(auto const& elem : v) { s << elem << ", "; }
return s;
}
And the main file, we firstly (indirectly) use the generic.h
and then, due to some other include, the vector overload:
// main.cpp
#include "generic.h"
#include "vector.h"
int main() {
std::vector<int> v{1,2,3,4,5};
shift(std::cout, v);
}
This code is accepted by GCC (5.4.0) and ICC (16.0), but clang complains call to function 'operator<<' that is neither visible in the template definition nor found by argument-dependent lookup
.
The annoying thing is that clang is right and I’d like to fix this in my code. There are as far as I can see three options:
-
Move the definition of
operator<<
beforeshift()
. This has the disadvantage that when including some (possibly other) files which indirectly includegeneric.h
andvector.h
, one would also have to take care to order them correctly. -
Use a custom namespace, import everything needed from
std
into that namespace and define the operator on the new-namespace classes inside that namespace, so that ADL can find it. -
Define
operator<<
in thestd
namespace. I think this is undefined behaviour.
Did I miss any option? What would be the best way in general to define overloads for functions of std
-only classes (the issue does not exist if I want to shift NS::MyClass
, since then I can just define the operator in NS
).
Aucun commentaire:
Enregistrer un commentaire