Структура рекурсивного соединения - PullRequest
0 голосов
/ 22 ноября 2018

У меня есть класс, который выглядит примерно так:

template<class KeyType, class... Types>
class BasicCompound
    {
    public:
        using mapped_type = std::variant
            <
              ValueWrapper<BasicCompound>
            , ValueWrapper<Types>...
            >;

        using key_type = KeyType;

       // Accessors for retreiving and modifying content
       // ...

    private:
        std::map<key_type, mapped_type> m_content;
    };

ValueWrapper решает поместить содержимое либо в строку, либо в std::unique_ptr.Было бы возможно с подобным интерфейсом, возможно через некоторый прокси, сделать рекурсивность необязательной?Под необязательным я подразумеваю, что пользователь не должен автоматически получать возможность хранить BasicCompound внутри себя, а скорее указывать его в списке типов.

Что я подумал:

  1. A using не работает.Сам по себе новый тип не может быть определен, и предопределение следующего определения типа не допускается.
  2. Добавление bool в список типов и использование std::conditional_t для mapped_type.Однако, если пользователь хочет сохранить X<BasicCompound>, этот подход не выполняется.
  3. Внедрить mapped_type извне.Тогда я не могу скрыть использование вещи ValueWrapper.
  4. Использование наследования над typdef подобно

    struct MyCompound : BasicCompound<std::string, MyCompound, int> {};
    

    Это работает, но тогда структура не является строго рекурсивной,поскольку MyCompound теперь отличается от BasicCompound.Возможно, CRTP-подобный подход мог бы решить эту проблему, но тогда внутренний составной тип должен обрабатываться иначе, чем другие типы.

1 Ответ

0 голосов
/ 23 ноября 2018

Нельзя использовать специализацию шаблона класса в качестве одного из аргументов шаблона этой специализации;нет никакого способа написать это, и его имя будет бесконечно длинным.Однако вы можете использовать оболочку для хранения рекурсивного типа:

template<class> class MaybeRecursive;

template<class T>
struct Wrapper {
  using type=T;
};
struct MRWrapper {
  using type=MaybeRecursive<MRWrapper>;
};

template<class T>
struct MaybeRecursive {
  using type=typename T::type;
  type *child;
};

void f() {
  int x;
  MaybeRecursive<Wrapper<int>> nonrec={&x};
  MRWrapper::type rec={&rec};
}

MRWrapper можно сделать шаблоном класса для предоставления дополнительных аргументов шаблона для MaybeRecursive.

...