Как избежать повторного ввода информации о типе для агрегатной инициализации? - PullRequest
4 голосов
/ 21 мая 2019

У меня есть следующий пример:

#include <array>

struct A {
    const char* str;
    const char* str2;
};

template<size_t N>
struct As {
    std::array<A,N> elems_;
};


template<class... Args>
As(Args...)->As<sizeof...(Args)>; //<-- NOTE: deduction guide !


constexpr static As as{A{"a","b"}, A{"1","2"}};//<-- 'retyping' A here


int main() {
  return as.elems_.size(); 
}

Ссылка на нерабочий пример

Пока этот код работает, я бы хотел избежать «перепечатывания»из A в агрегированном списке, но если я пропущу его, руководство по выводу завершится неудачно с: "cannot deduce template arguments for 'As'" (что, я думаю, имеет смысл).Возможно, один из способов исправить это - написать любое количество руководств по выводам, которое мне нужно с тех пор, как я могу написать тип A в каждом руководстве по выводам (то есть: одно вычет для каждого размера контейнера, который мне нужен).

1 Ответ

5 голосов
/ 21 мая 2019

Инициализация вложенных агрегатов имеет более или менее удивительное поведение, которое вы не добавляете для соответствия вложенным { / }.

Например, это , как вы инициализируете std::array<std::array<int, 2>, 2>:

std::array<std::array<int, 2>, 2> arr = { 1, 1, 2, 2 };

Выполнение { {1, 1}, {2, 2} } не не работает!

Аналогично, для агрегатной инициализации в вашем случае не потребуется вложенный { / } с уже выполненным CTAD (ну, с заданным параметром шаблона):

constexpr static As<2> as{"a","b", "1","2"}; // Ok!

Зная это, мы можем просто добавить следующее руководство по выводам:

template<class ... Ts>
As(Ts...) -> As<(sizeof...(Ts) + 1)/2>;

Это выбирает N как «половину количества аргументов». И действительно, теперь вы можете инициализировать так:

constexpr static As as{"a","b", "1","2"}; // Deduces N = 2.

Демо: https://godbolt.org/z/oznEwl

Да, это теряет возможность структурировать ввод с помощью { / } для лучшей читаемости, но я виню здесь инициализацию агрегата (см. Пример с вложенным массивом выше).

...