Инициализировать агрегатный элемент в общем коде шаблона

Например,

template <typename T>
struct node {
  T data;
  node* pnext;
};

template <typename T, typename... Us>
void func(Us&&... args) {
  // Initialize a node<T> with data initialized from args...
}

Пути, которые я могу придумать, и их ограничения.

  1. node<T> v{ T(forward<Us>(args)...) }, Это включает в себя инициализацию копирования, которая не работает, если T не копируемый и неподвижный, например, атомарный тип.

  2. node<T> v{ {forward<Us>(args)...} }, Это включает copy-list-initialization, которая не работает, если выбранный конструктор является явным. Например, node<unique_ptr<int>> n{ {new int()} } не работает

Я предполагаю, что вопрос решен, если я могу как-то напрямую инициализировать (например, direct-list-initialization) агрегатный член. Тем не менее, я не понимаю, как это возможно, кроме написания пользовательского конструктора, что делает node неагрегированный тип, который является излишним, и я не хочу этого делать. Любая идея?

1 ответ

Решение

C++14 не имеет эффективного решения этой дилеммы. Ну, пока еще не используется агрегатная инициализация. Если вы даете node<T> конструктор переменных, тогда он может передать параметры непосредственно инициализатору элемента:

template <typename T>
struct node {
  T data;
  node* pnext;

  template<typename ...Args>
  node(Args ...&&args) : data(std::forward<Args>(args)...) {}
};

Таким образом, позволяя вам вызвать node<T> v( T(forward<Us>(args)...) ), Конечно, это больше не совокупность.

Правила гарантированного отбора в C++17 позволяют node<T> v{ T(forward<Us>(args)...) } не провоцировать копию или переместить.

Другие вопросы по тегам