誰もが違いを感じることができなければ、標準ではそれを取り除くことができます。あなたは正しい方法で、forward_list
にPTMFを合法的に作成できないので、あなたはそう安全です。
カスタムアロケータの危険性は既に指摘されています。しかし、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
。
更新
あなたが呼び出し可能な「静的」な過負荷を作りたい場合は、単に少しより望ましい「静的でない」オーバーロードよりも、それをする必要があります。今テストは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();
}
:それを行う方法の1つは「静的ではない」過負荷を変化させています。
リストの操作を変更するには、リストのアロケータにアクセスする必要があるため、静的になる可能性はありません(特に、新しいステートフルなアロケータを使用すると)。 –
しかし、テンプレートは、非常に一般的な 'std :: allocator'の場合に特化することができ、必要に応じてユーザ自身が同様に特殊化することができます。 – Potatoswatter
* iterator *に関する知識に基づいて、これをどのように特化しますか?イテレータは、それがどのリストに属しているか、どのリストが使用するアロケータでもわからない。 –