Here是一個關於如何區分填充和範圍構造函數的問題。代碼複製到此處:C++:SFINAE區分填充和範圍構造函數嗎?
template <typename T>
struct NaiveVector {
vector<T> v;
NaiveVector(size_t num, const T &val) : v(num, val) { // fill
cout << "(int num, const T &val)" << endl;
}
template <typename InputIterator>
NaiveVector(InputIterator first, InputIterator last) : v(first, last) { // range
cout << "(InputIterator first, InputIterator last)" << endl;
}
};
上述代碼不起作用,如該問題中所述。該溶液是用SFINAE以限定的範圍內的構造,這樣example:
template
<
typename InputIterator
, typename = typename ::std::enable_if
<
::std::is_same
<
T &
, typename ::std::remove_const
<
decltype(*(::std::declval<InputIterator>()))
>::type
>::value
, void
>::type
>
NaiveVector(InputIterator first, InputIterator last) : v(first, last)
{
cout << "(InputIterator first, InputIterator last)" << endl;
}
該溶液的這一主旨與T &
比較解除引用類型的InputIterator
。如果它確實是一個指向T
的迭代器,則std::is_same
的比較將爲真,並且範圍構造函數將被選中;如果它不是迭代器,將會出現模板替換失敗,所以範圍構造函數將被刪除,因此將選擇填充構造函數。
但是,上述解決方案存在問題。如果輸入InputIterator
是const_iterator
型的(例如cbegin()
),則解除引用它會產生一個const T &
,其const
-ness不能通過std::remove_const
被移除(解釋here),所以在std::is_same
的比較將是假的,導致範圍構造被錯誤地刪除。
GNU的C++ STL有bug可能(我猜)因爲這個原因。在這個bug中,該方法只接受迭代器,但不接受const_iterator。
問題:
(1)是有更好解決方法不是兩個std::is_same
條件通過OR運算符與const T &
組合,一個具有T &
比較解除引用的類型,其他? (2)如果採用(1)中描述的解決方法,則仍然需要std::remove_const
,現在它不能從引用類型中刪除const
-ness,並且取消引用(const或非const)迭代器總是會產生參考文獻const T &
或T &
。
'的std :: is_constructible())>'似乎甚至更好(它處理'的std ::矢量'的可能布爾包裝器)。 –
Jarod42
@ Jarod42 ..它可以處理這個問題中說的問題嗎?對不起,我現在不在電腦附近。 – user8385554
「std :: vector:erase」的錯誤與SFINAE無關。 – Jarod42