標準では、誰も違いがわからない場合は問題なく使用できるとされています。そして、合法的に 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
したがって、静的にすることは不適合です。
アップデート
「静的」オーバーロードを呼び出し可能にしたい場合は、単に「非静的」オーバーロードよりも望ましいものにする必要があります。これを行う 1 つの方法は、「非静的」オーバーロードを次のように変更することです。
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
これで、メンバー関数が静的かどうかに応じて、テストは「静的」または「静的ではない」のいずれかを出力します。