Тема: Шаблони вузлів (node). template<typename T, unsigned int N, ...>
Попередня назва: "Наслідування шаблонів. template<typename T, typename N = Node<T, N>>"
Ідея така:
Є різні структури вузлів, які містять різну кількість вказівників на інші вузли такого ж типу як вони самі (в даному прикладі спрощено до двох: Node, DualNode). Всі вузли містять якісь дані, які загалом можуть бути довільного типу, тому я спочатку зробив з них наступні шаблони:
// Node.h
#pragma once
template<typename T>
struct Node
{
T data;
Node *next;
};
і
// DualNode.h
#pragma once
#include"Node.h"
template<typename T>
struct DualNode : public Node<T>
{
DualNode *prev;
};
Виглядає наче все добре, але є проблема.
Якщо я створю екземпляр DualNode, то його поле next буде мати тип Node, а не DualNode:
DualNode<int> dnode;
dnode.next = new DualNode<int>(); // Це добре.
dnode.next = new Node<int>(); // Це погано.
Для того щоб рішити проблему, переписав шаблони так:
// Node.h
#pragma once
template<typename T, typename N = Node<T, N>>
struct Node
{
T data;
N *next;
};
// DualNode.h
#pragma once
#include"Node.h"
template<typename T, typename N = DualNode<T, N>>
struct DualNode : public Node<T, N>
{
N *prev;
};
Але компілятор (Visual Studio 2013) видав, що не знає, що таке N
Error C2065: необявлений N.
Я спробував його забрати:
// Node.h
#pragma once
template<typename T, typename N = Node<T>>
struct Node
{
T data;
N *next;
};
// DualNode.h
#pragma once
#include"Node.h"
template<typename T, typename N = DualNode<T>>
struct DualNode : public Node<T, N>
{
N *prev;
};
Компілятор видав, що це жорстоке поводження з компілятором
Error C1202: Надто складно, або рекурсія.
Ну я в тирнеті надибав приклади парних шаблонів, зробив по образу і подобію:
// Node.h
#pragma once
template<typename T, typename N = Node<T, N>>
struct Node
{
T data;
N *next;
};
template<typename T>
struct Node : public Node<T, Node<T>>
{ };
// DualNode.h
#pragma once
#include"Node.h"
template<typename T, typename N = DualNode<T, N>>
struct DualNode : public Node<T, N>
{
N *prev;
};
template<typename T>
struct DualNode : public DualNode<T, DualNode<T>>
{ };
Компілятор:
Error C2955: для використання класу шаблон треба список аргументів.
Error C2976: мало аргументів.
І це печально.
Використовувати всюди static_cast, dynamic_cast і подібні для мене не варіант.
Чи є якийсь культурний спосіб описати ці структури так, щоб зберегти наслідування і гарантувати користувачам, що поле DualNode::next буде вказівником на DualNode ?
І як ?