Question:
I’ve copied code from this wiki and it works.The problem occurs when I make this code:
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:
The functional cast:
random_v = std::vector<int>(getRandomN(10));
Clearly, the type must be repeated twice.
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 convertgetRandomN(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]
template
using BackInsertable = decltype(std::declval
class getRandomN
{
size_t count;
public:
getRandomN(int n = 1) : count(n) {}
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]
If you have better answer, please add a comment about this, thank you!