• python
  • javascript
  • reactjs
  • sql
  • c#
  • java
Facebook Twitter Instagram
Devs Fixed
  • python
  • javascript
  • reactjs
  • sql
  • c#
  • java
Devs Fixed
Home ยป Resolved: Return Type Resolver and ambiguous overload for ‘operator=’

Resolved: Return Type Resolver and ambiguous overload for ‘operator=’

0
By Isaac Tonny on 16/06/2022 Issue
Share
Facebook Twitter LinkedIn

Question:

I’ve copied code from this wiki and it works.
The problem occurs when I make this code:
My compiler (gcc trunk) prints out this error:
I don’t understand why the C++ compiler can’t simply take copy operator= but try to match operator=(initializer_list<value_type> __l) and operator=(vector&& __x) instead.
Here is my solution to this problem, which I don’t like, but I can’t think of anything else:
  1. The functional cast:

    random_v = std::vector<int>(getRandomN(10));
    

    Clearly, the type must be repeated twice.

  2. Private inheritance and forwarding required methods from the parent:

    template<typename T>
    class my_vector : private std::vector<T>
    {
    public:
        using std::vector<T>::end;
        using std::vector<T>::insert;
    
        my_vector<int>& operator=(my_vector<int> rhs) noexcept
        {
            std::swap(*this, rhs);
            return *this;
        }
    };
    
    my_vector<int> random_v1;
    random_v1 = getRandomN(10);
    

    Clearly, I don’t use std::vector<int> anymore…


The whole code: godbolt

Answer:

The issue is that, from the conversion operator’s signature alone, the compiler can’t tell if it should convert getRandomN(10) to a std::initializer_list<int> and then assign that to random_v or convert getRandomN(10) to a std::vector<int> and then assign that to random_v. Both involve exactly one user-defined conversion, and so neither is a better choice from the compiler’s point of view.
Of course, once you look at the body of the conversion operator it becomes clear that std::initializer_list<int> won’t work, since it has no insert member function, but that’s too late. The compiler makes its choice for overload resolution before looking at the body of the function.
The way to make this work is to make it clear that std::initializer_list<int> isn’t the right choice from the signature alone. If you have access to C++20 concepts that’s pretty easy:

template
concept BackInsertable = requires(T t) { t.insert(std::end(t), 0); };

class getRandomN
{
size_t count;

public:
getRandomN(int n = 1) : count(n) {}

// —— vvvvvvvvvvvvvv —— NOTE HERE
template
operator Container () {
Container c;
for(size_t i = 0;i < count; ++i) c.insert(c.end(), rand()); // push_back is not supported by all standard containers. return c; } }; [/code]

Without concepts you’ll need to use other SFINAE tricks to make that operator invalid. Here’s one possible implementation that works all the way back to C++11:

template
using BackInsertable = decltype(std::declval().insert(std::end(std::declval()), 0));

class getRandomN
{
size_t count;

public:
getRandomN(int n = 1) : count(n) {}

template * = nullptr>
operator Container () {
Container c;
for(size_t i = 0;i < count; ++i) c.insert(c.end(), rand()); // push_back is not supported by all standard containers. return c; } }; [/code]

If you have better answer, please add a comment about this, thank you!

c++ inheritance oop stl vector
Share. Facebook Twitter LinkedIn

Related Posts

Resolved: VBA – Applying border around the areas with value/text

01/04/2023

Resolved: How can I implement a function depending on picked up items?

01/04/2023

Resolved: Azuer Service Bus SDK not receiving the specified messages

01/04/2023

Leave A Reply

© 2023 DEVSFIX.COM

Type above and press Enter to search. Press Esc to cancel.