template <class Data, class Allocator = std::allocator<Node> >
class Node : public Data {
// ...
};
質問は簡単です。上記のコードをコンパイルするにはどうすればよいですか? その意図は、ノードに他のノードを割り当てる可能性を与えることです (そしてデフォルトのアロケータを提供することです)。
template <class Data, class Allocator = std::allocator<Node> >
class Node : public Data {
// ...
};
質問は簡単です。上記のコードをコンパイルするにはどうすればよいですか? その意図は、ノードに他のノードを割り当てる可能性を与えることです (そしてデフォルトのアロケータを提供することです)。
最後に私はそれを解決しました!解決策は、Node が既に定義されているクラスの内部まで、デフォルトのアロケーターの特殊化を遅らせることです。
template <class Data, template<class T> class TAllocator = std::allocator >
class Node : public Data {
typedef TAllocator<Node> Allocator;
// ...
};
次のように書くことはできません。
template <class Data, class Allocator>
class Node;
template <class Data, class Allocator =
std::allocator<Node<Data, std::allocator<Node<...> >
class Node : public Data {
// ...
};
デフォルトの引数はそれ自体を繰り返す必要があるためです。ただし、タグタイプを使用できます
struct DefaultAllocatorTag { };
template<typename Alloc, typename Node>
struct SelectAllocator {
typedef Alloc type;
};
template<typename Node>
struct SelectAllocator<DefaultAllocatorTag, Node> {
typedef std::allocator<Node> type;
};
template <class Data, class Allocator = DefaultAllocatorTag >
class Node : public Data {
typedef typename SelectAllocator<Allocator, Node>::type
NodeAllocator;
};
ただし、該当する場合は、コンテナー内のアロケーターを決定します。このような:
template<typename Data, typename Allocator = std::allocator<Data> >
struct Container {
struct Node : Data {
typedef typename Allocator::template rebind<Node>::other NodeAllocator;
...
};
...
};
これはどう?:
#include <memory>
template<class Data>
class NodeImpl : public Data
{
};
template<class Data, class Allocator = std::allocator< NodeImpl<Data> > >
class Node : public NodeImpl<Data>
{
};
class MyAllocator
{
};
class MyDataClass
{
};
int main()
{
Node<MyDataClass> node;
Node<MyDataClass, MyAllocator> node_with_alloc;
return 0;
}
コンパイルすることはできません-作成しようとしているのは「無限」タイプです。
まず、インスタンス化されていないクラス テンプレートをテンプレート引数として使用することはできません。したがって、次のように Node を std::allocator に渡す必要があります。
template <class Data, class Allocator = std::allocator<Node<Data, Something> > >
class Node ...
しかし、それは何でしょう?さて、std::アロケータ
トリックは、アロケーターがテンプレート引数だけでなく、他の型を割り当てる必要があることです。クラスを次のように宣言します
template <class Data, class Allocator = std::allocator<Data> > class Node ...
次に、次のようにノードのアロケーターを作成します。
typename Allocator::rebind<Node>::other nodeAllocator(myDataAllocator)
アロケーターに関するこの vcblog の投稿は役立つかもしれませんが、イテレーターに重点が置かれすぎています。
別の解決策。こちらの方が典型的なようです。すなわち。ベクトルとスマート ポインターの実装は、似たようなものを使用しています。アイデアは、アロケータからプライベートに継承することです:
template <class Data, template <class N> class Allocator = std::allocator>
class Node : public Data, private Allocator<Node<Data, Allocator> > {
// ...
};
おまけに、継承宣言では既に Node.js を使用できます。