Ответ 1
Невозможно реализовать связанный список таким образом, потому что ваш тип node
всегда будет неполным. Вот более полный пример, который иллюстрирует проблему:
#include <iostream>
#include <experimental/optional>
template <typename T>
struct node {
std::experimental::optional<node<T>> next;
T data;
};
int main( int, char ** )
{
std::cout << sizeof( node<int> ) << std::endl;
return 0;
}
Дело в том, что optional<T>
требует завершения T
, но в точке, где вы определяете next
, node
является неполным. Причина, по которой optional<T>
требует полного типа, заключается в том, что он хранит T
непосредственно внутри объекта optional
, то есть не выделяет память в куче. В результате он должен знать размер T
. Внутри он содержит буфер sizeof( T )
. Что касается макета памяти, вы можете думать о optional<T>
как
template <class T>
struct optional
{
bool _containsValue;
char _buffer[ sizeof( T ) ];
};
но на практике это сложнее из-за требований к выравниванию памяти.
В вашем случае, чтобы узнать размер optional<node>
, он должен знать размер node
, и для этого он должен знать размер optional<node>
.