Search code examples
c++namespacesoperator-overloadingoverload-resolutionname-lookup

Why doesn't the << operator defined inside a namespace participate in overload resolution?


In the following scenario, the operator<< function participates in overload resolution (when it is in the global namespace):

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec) {
    os << '[';
    for (const T &val : vec)
        os << val << ", ";
    return os << "\b\b]";
}

... but below, when defined inside a namespace, it does not:

namespace blah {
    template <typename T>
    std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec) {
        os << '[';
        for (const T &val : vec)
            os << val << ", ";
        return os << "\b\b]";
    }
}

When called from main, as such:

int main() {
    std::vector<int> vec{5, 4, 3, 6, 4, 3, 5, 6, 8, 1};
    std::cout << vec << std::endl;
    return 0;
}

... the compiler is not able to find the operator<< overload when it is defined in blah.

What is going on?

Edit:

When calling the overload with the scope resolution operator, everything compiles fine:

blah::operator<<(std::cout, vec);

Why is this?


Solution

  • In the first case, there is used unqualified name lookup and/or ADL (argument-dependent lookup) lookup that includes the global namespace where the operator is declared.

    In the second case, the operator will not be found because the namespace blah is not considered for unqualified name lookup.

    Either you could use qualified the name, like:

    blah::operator <<( std::cout, vec ) << std::endl;
    

    Or, you could use a using directive to include the namespace blah in the set of namespaces for unqualified name lookup, as:

    using namespace blah;
    std::cout << vec << std::endl;