2

I created a class named MyClass in namespace N. Now I define a global operator== in namespace N.

namespace N
{
class MyClass
{
// member function begin()
// member function end()
// content omitted
}

template<typename T>
bool operator==(const MyClass& a_mc, const T& a_other)
{
    using namespace std;
    return std::equal(a_mc.begin(), a_mc.end(), begin(a_other));
}
}

This results in other code failing to compile with (included-from-stack omitted):

error: ambiguous overload for 'operator==' (operand types are 'std::basic_string_view' and 'const char [3]')

note: candidate: 'bool N::operator==(const N::MyClass&, const T&) [with T = char [3]]'

note: candidate: 'constexpr bool std::operator==(std::basic_string_view<_CharT, _Traits>, std::__detail::__idt >) [with _CharT = char; _Traits = std::char_traits; std::__detail::__idt > = std::basic_string_view]' 479 |
operator==(basic_string_view<_CharT, _Traits> __x

Why is N::operator== even considered?

--

Edit first code that hit the problem was

bool N::MyClass::f(const std::string_view& a_thing)
{return a_thing.substr(0,2) == "XY";}

--

Minimal working example:

#include <algorithm>
#include <string_view>
#include <type_traits>

namespace N
{
        struct MyClass
        {
                MyClass() noexcept = default;
                template<typename T,
                        typename = std::void_t<decltype(T{}.data())>,
                        typename = std::void_t<decltype(T{}.size())>>
                MyClass(const T& a_source)
                {}

                const char* begin() const { return 0; } // stub
                const char* end() const { return 0; } // stub
                bool f(const std::string_view& a_thing);
        };

        template<typename T>
        bool operator==(const MyClass& a_mc, const T& a_other)
        {
            using namespace std;
            return std::equal(a_mc.begin(), a_mc.end(), begin(a_other));
        }

        bool MyClass::f(const std::string_view& a_thing)
        {
                return a_thing.substr(0,2) == "XY";
        }
}

Compile with

g++ -std=c++17 example.cpp

7
  • 3
    N::operator== is considered for what? please provide a minimal reproducible example. Commented Jan 15, 2020 at 18:33
  • 1
    we need a complete reproducible example. I do know what code I have to add to get a similar error, but I have no clue what code you have, so it is impossible to answer in a meaningful way Commented Jan 15, 2020 at 18:38
  • 2
    does MyClass have a converting constructor? Commented Jan 15, 2020 at 18:46
  • Cannot reproduce: ideone.com/2J6idF Commented Jan 15, 2020 at 18:48
  • using namespace std; return std::equal(...); Pretty meaningless, isn't it? Normally you'd have using std::equal; return equal(...);. Commented Jan 15, 2020 at 18:55

1 Answer 1

2

MyClass has a template constructor that works with std::string_view.

Since the constructor is not marked explicit the compiler is allowed to use it for implicit conversions.

That means that when you do

bool N::MyClass::f(const std::string_view& a_thing)
{return a_thing.substr(0,2) == "XY";}

the compiler is allowed to convert a_thing.substr(0,2) to a MyClass and then it could be used to call your bool operator==.

One way to avoid things like this is to make the constructor of MyClass explicit.

template<typename T,
    typename = std::void_t<decltype(T{}.data())>,
    typename = std::void_t<decltype(T{}.size())>>
    explicit MyClass(const T& a_source)
    {}
Sign up to request clarification or add additional context in comments.

3 Comments

Why does the error message state that the operand types are 'std::basic_string_view' and 'const char [3]'?
The left-hand-side is a std::string_view and the right hand side is "XY" which get deduces as const char [3] by the template.
@std_unordered_map Another way to put it is that if your operator== did not exist "XY" would be converted to a std::string_view. But since both that and your operator== requires 1 conversion to work it is ambiguous which one should be preferred.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.