Иногда полезно создать экземпляр стандартного контейнера с неполным типом для получения рекурсивной структуры:
struct multi_tree_node { // Does work in most implementations
std::vector< multi_tree_node > child;
};
struct trie_node { // Does not work in most implementations
std::map< char, trie_node > next;
};
Это работает, потому что контейнеры не имеют членов типа value_type
или функций-членов, которые передают или возвращают любые объекты value_type
по значению. Стандарт, похоже, не очень много говорит о неполных аргументах шаблона, но есть один бит в С++ 11 §17.6.4.8 [lib.res.on.functions], "требования к другим функциям":
В частности, эффекты undefined в следующих случаях:... если неполный тип (3.9) используется в качестве аргумента шаблона при создании экземпляра компонента шаблона, если это специально не разрешено для этого компонента.
Означает ли это, что приведенные выше конструкции незаконны, даже если экземпляры не находятся в блочной области? Подходит ли это к "операциям над типами, используемыми для создания стандартных компонентов шаблона библиотеки" (также 17.6.4.8)? Или реализация библиотеки запрещена для выполнения экземпляров шаблонов, которые могут быть неудачными для неполных типов, когда все требуемые экземпляры успешно выполняются?
Изменить: Поскольку только функции могут вызывать и создавать экземпляры других функций, ограничение "операций с типами..." с теми, которые находятся в области блока, похоже, будет содержать содержимое функций-членов более строгому требованию, чем содержимое подписи и определения классов членов. В конце концов, это не имеет смысла делать что-либо с помощью multi_tree_node
до тех пор, пока тип не будет завершен. И это распространяется на std::unique_ptr
, который явно поддерживает аргумент неполного типа, даже если он используется в области блока.
Изменить 2: Служит мне правильно, чтобы не потрудиться протестировать пример trie_node
- и я даже пробовал его раньше. Это так же, как пример обрыва в статьи, который @Ise связан. Тем не менее, хотя статья кажется само собой разумеющейся, что "ничего подобного не могло бы работать", решение кажется мне простым - std::map
Внутренний tree_node
класс должен быть шаблоном без члена, а не членом класса non-template.
Во всяком случае, эта статья очень хорошо устанавливает намерение дизайна, поэтому я думаю, что моя проблема в том, что она находится под подзаголовком "требований к функциям", это только так.