我已經從這個 wiki復制了代碼并且它可以作業。
當我撰寫此代碼時會出現問題:
int main()
{
std::set<int> random_s = getRandomN(10);
std::vector<int> random_v;
random_v = getRandomN(10);
std::list<int> random_l = getRandomN(10);
}
我的編譯器(gcc trunk)列印出這個錯誤:
error: ambiguous overload for 'operator=' (operand types are 'std::vector<int, std::allocator<int> >' and 'getRandomN')
43 | random_v = getRandomN(10);
我不明白為什么 C 編譯器不能簡單地采用copy operator=而是嘗試匹配operator=(initializer_list<value_type> __l)and operator=(vector&& __x)。
這是我對這個問題的解決方案,我不喜歡,但我想不出別的:
功能型演員:
random_v = std::vector<int>(getRandomN(10));顯然,該型別必須重復兩次。
來自父級的私有繼承和轉發所需的方法:
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);很明顯,我不再使用
std::vector<int>了...
整個代碼:godbolt
uj5u.com熱心網友回復:
問題在于,僅從轉換運算子的簽名來看,編譯器無法判斷它是否應該轉換getRandomN(10)為 astd::initializer_list<int>然后將其分配給random_v或轉換getRandomN(10)為 astd::vector<int>然后將其分配給random_v。兩者都只涉及一個用戶定義的轉換,因此從編譯器的角度來看,兩者都不是更好的選擇。
當然,一旦您查看轉換運算子的主體,就會發現它std::initializer_list<int>不起作用,因為它沒有insert成員函式,但為時已晚。編譯器在查看函式體之前選擇多載解決方案。
完成這項作業的方法是明確這std::initializer_list<int>不是僅從簽名中做出的正確選擇。如果您可以訪問非常簡單的 C 20 概念:
template <typename T>
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 <BackInsertable Container>
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;
}
};
如果沒有概念,您將需要使用其他 SFINAE 技巧來使該運算子無效。這是一種可以追溯到 C 11 的可能實作:
template <typename T>
using BackInsertable = decltype(std::declval<T&>().insert(std::end(std::declval<T&>()), 0));
class getRandomN
{
size_t count;
public:
getRandomN(int n = 1) : count(n) {}
template <typename Container, BackInsertable<Container>* = 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;
}
};
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/494858.html
