Here, Is x
a std::vector<int>
or a std::vector<std::vector<int>>
?
其他答案在這裏解決您的其他問題,但我想解決這個問題更徹底一點。當我們正在做類模板參數推導時,我們從構造函數synthesize a bunch of function templates,然後從deduction guides更多一些,並執行重載決議,以確定正確的模板參數。
有相當多的構造是std::vector<T,A>
,但他們大多不提T
這將使T
非推斷上下文,因此不會在此重載一個可行的選擇。如果我們預先修剪設置爲只使用那些可能是可行的:通過降低分配器
template <class T> vector<T> __f(size_t, T const&); // #2
template <class T> vector<T> __f(vector<T> const&); // #5
template <class T> vector<T> __f(vector<T>&&); // #6, NB this is an rvalue ref
template <class T> vector<T> __f(initializer_list<T>); // #8
然後還該deduction guide,這也是我將簡化:
template <class InputIt>
vector<typename std::iterator_traits<InputIt>::value_type> __f(InputIt, InputIt);
這些都是我們的5位候選人,我們像[dcl.init]一樣通過__f({v.begin(), v.end()})
致電超載。因爲這是列表初始化,所以我們start with the initializer_list
candidates,並且,如果沒有的話,我們是否會進入其他候選者。在這種情況下,有一個initializer_list
候選人是可行的(#8),所以我們選擇它甚至沒有考慮任何其他人。該候選者將T
推導爲std::vector<int>::iterator
,因此我們接着重新啓動重載解析過程,以選擇std::vector<std::vector<int>::iterator>
列表的構造函數,並使用兩個迭代器進行初始化。
這可能不是理想的結果 - 我們可能想要一個vector<int>
。該解決方案有很簡單:使用()
S:
std::vector x(v.begin(), v.end()); // uses explicit deduction guide
現在,我們沒有做列表初始化所以initializer_list
候選人是不是一個可行的候選者。因此,我們通過扣除指南(唯一可行的候選者)推導出vector<int>
,並最終調用它的迭代器對構造函數。這有實際使評論正確的副作用。
這是很多地方與{}
初始化做一些事情比()
初始化完全不同的一個。有人認爲{}
是統一的初始化 - 像這樣的例子似乎反對。我的經驗法則:當你特意使用{}
時,有意識地需要{}
提供的行爲。否則爲()
。
'x'可能是'std :: vector :: iterator>'。 –
嘗試添加值到x看到:[演示](http://coliru.stacked-crooked.com/a/640910c60c5735c1)所以'std :: vector :: iterator>'。 –
Jarod42
你知道一般的演繹指南嗎?如果沒有,[this](http://en.cppreference.com/w/cpp/language/class_template_argument_deduction#User-defined_deduction_guides)可能會有用。 – HolyBlackCat