Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A flaw in C++ overload resolution rules?

Consider the following code:

#include <iostream>

namespace ns1
{
    struct A
    {
    };

    template <class T>
    std::ostream& operator << (std::ostream& os, const T& t)
    {
        return os << "ns1::print" << std::endl;
    }
}

namespace ns2
{
    template <class T>
    std::ostream& operator << (std::ostream& os, const T& t)
    {
        return os << "ns2::print" << std::endl;
    }

    void f (const ns1::A& a)
    {
        std::cout << a;
    }
}


int main()
{
    ns1::A a;

    ns2::f (a);

    return 0;
}

Compilation fails with "ambiguous overload error" as per standard.

But why? Surely "equally good" operator in A's 'home' namespace should take precedence? Is there any logical reason not to do it?

like image 453
cppalex Avatar asked Feb 25 '16 17:02

cppalex


People also ask

What does overload resolution failed mean?

It generates this error message when one overload is more specific for one argument's data type while another overload is more specific for another argument's data type.

What is the overload resolution?

The process of selecting the most appropriate overloaded function or operator is called overload resolution. Suppose that f is an overloaded function name. When you call the overloaded function f() , the compiler creates a set of candidate functions.

Where can an ambiguity occur in overloading a function?

In Function overloading, sometimes a situation can occur when the compiler is unable to choose between two correctly overloaded functions. This situation is said to be ambiguous. Ambiguous statements are error-generating statements and the programs containing ambiguity will not compile.

What is ambiguity in function overloading?

When the compiler is unable to decide which function it should invoke first among the overloaded functions, this situation is known as function overloading ambiguity. The compiler does not run the program if it shows ambiguity error.


1 Answers

If you want the overload in namespace A to be preferred than you'll have to add something to it to make it actually better. Say, by making it not a template:

namespace ns1 
{
    std::ostream& operator<<(std::ostream&, const A& );
}

Otherwise, there's really no conceptual reason to see why a function template in one namespace would be preferred to a function template in another namespace if both are exactly equivalent. After all, why would the function template in A's namespace be "better" than the function template in f's namespace? Wouldn't the implementer of f "know better"? Relying solely upon function signature sidesteps this issue.

like image 69
Barry Avatar answered Oct 24 '22 19:10

Barry