標準說如果沒人能分辨出來,你就可以逃脫。而且你無法合法地創建一個PTMF到forward_list
,這樣你就很安全。
自定義分配器的危險已經被指出。但即使對於std::allocator<T>
,也存在某個人可能專注於std::allocator<MyType>
然後檢測到allocator::construct/destroy
未被調用的危險。
好的,但可以專門說std::forward_list<int>
(沒有自定義分配器,沒有用戶定義的value_type),並使insert_after
靜態?
不可以。使用新的SFINAE功能可以檢測到此更改。這裏是一個演示:
#include <memory>
#include <iostream>
template <class T, class A = std::allocator<T>>
class forward_list
{
public:
typedef T value_type;
struct const_iterator {};
struct iterator {};
iterator insert_after(const_iterator p, const T& x);
};
template <class C>
auto test(C& c, typename C::const_iterator p, const typename C::value_type& x)
-> decltype(C::insert_after(p, x))
{
std::cout << "static\n";
return typename C::iterator();
}
template <class C>
auto test(C& c, typename C::const_iterator p, const typename C::value_type& x)
-> decltype(c.insert_after(p, x))
{
std::cout << "not static\n";
return typename C::iterator();
}
int main()
{
::forward_list<int> c;
test(c, ::forward_list<int>::const_iterator(), 0);
}
的運行程序,並打印出:
not static
但是,如果我做insert_after
靜:
static iterator insert_after(const_iterator p, const T& x);
然後我得到一個編譯時錯誤:
test.cpp:34:5: error: call to 'test' is ambiguous
test(c, ::forward_list<int>::const_iterator(), 0);
^~~~
test.cpp:16:6: note: candidate function [with C = forward_list<int, std::__1::allocator<int> >]
auto test(C& c, typename C::const_iterator p, const typename C::value_type& x)
^
test.cpp:24:6: note: candidate function [with C = forward_list<int, std::__1::allocator<int> >]
auto test(C& c, typename C::const_iterator p, const typename C::value_type& x)
^
1 error generated.
檢測到差異。
因此它是不符合使forward_list::insert_after
靜態。
更新
如果你想使「靜態」超載調用,只需讓它稍微比「並不是一成不變的」超載較爲理想。這樣做的一個辦法是改變「不是靜態的」過載:
template <class C, class ...Args>
auto test(C& c, typename C::const_iterator p, const typename C::value_type& x, Args...)
-> decltype(c.insert_after(p, x))
{
std::cout << "not static\n";
return typename C::iterator();
}
現在測試將顯示出無論是「靜態」或「不是靜態的」,這取決於insert_after
成員函數是靜態的還是沒有。
變異列表操作需要訪問列表的分配器,所以我懷疑它們可能是靜態的(特別是對於新的有狀態分配器)。 –
儘管如此,模板可以專門用於'std :: allocator'這個非常常見的情況,如果需要的話,用戶也可以自己選擇。 – Potatoswatter
你會如何根據關於* iterator *的知識來專門做這件事?迭代器不知道它屬於哪個列表,也不知道該列表使用哪個分配器。 –