Я подозреваю, что там как минимум две разные проблемы.
Правильно: я вижу три разные проблемы.
1) std::list
потребности два параметра шаблона;второй по умолчанию (std::allocator<T>
, где T
- первый параметр шаблона);а также векторам, запросам, наборам и т. д. требуется больше, чем параметр шаблона (некоторые по умолчанию).
То есть template<template<class> class>
не соответствует std::list
и другим контейнерам STL.
КомуЕсли говорить более обобщенно, я предлагаю что-то вроде
template <template <typename...> class Iterable, typename ... Ts>
A (Iterable<int, Ts...> & it);
2) A b = {1, 2, 3, 4};
не работает, потому что вы вызываете конструктор с четырьмя аргументами и у вас есть только конструкторы с одним аргументом.Таким образом, вы должны явно указать контейнер как
A b = std::list<int>{1, 2, 3, 4};
Учитывая, что вы ожидаете std::initializer_list
в качестве контейнера по умолчанию, если вы соглашаетесь удваивать графики ({ { 1, 2, 3, 4 } }
вместо { 1, 2, 3, 4 }
для передачиодин аргумент для конструктора), вы можете указать std::initializer_list
(или другой контейнер, если хотите) по умолчанию Iterable
.
Я имею в виду ... если вы объявите конструктор следующим образом
template <template <typename...> class Iterable = std::initializer_list,
typename ... Ts>
A (Iterable<int, Ts...> const & it);
, затем вы можете инициализировать b
как
A b {{1, 2, 3, 4}};
3) подпись Iterable<int, Ts...> & it
, в вашем конструкторе шаблона, принять ссылку на l-значение, поэтому принимайте
list<int> l = {1, 2, 3, 4};
A a(l);
, но не принимает
A b = std::list<int>{1, 2, 3, 4};
, поскольку std::list<int>{1, 2, 3, 4}
является значением r.
Чтобы решить эту проблему, вы можете написать другой конструктор для ссылок на значения r, но,в этом случае я подозреваю, что приемлемо просто изменить конструкцию шаблона, чтобы она могла принимать const l-значения ссылок
A (Iterable<int, Ts...> const & it);
// .....................^^^^^
Бонус (не по теме) предложение: если вы 'Заинтересовавшись принятием контейнеров STL, вы можете упростить свой шаблонИспользовать конструктор, используя конструктор l
, который принимает пару итераторов (begin()
, end()
), поэтому
template <template <typename...> class Iterable, typename ... Ts>
A::A (Iterable<int, Ts...> const & it) : l{it.cbegin(), it.cend()}
{ }
или также
template <template <typename...> class Iterable, typename ... Ts>
A::A (Iterable<int, Ts...> const & it) : l{std::cbegin(it), std::cend(it)}
{ }
Ниже приведен ваш кодмодифицированный
#include <initializer_list>
#include <iostream>
#include <list>
struct A
{
std::list<int> l;
template <template <typename...> class Iterable = std::initializer_list,
typename ... Ts>
A (Iterable<int, Ts...> const & it);
};
template <template <typename...> class Iterable, typename ... Ts>
A::A (Iterable<int, Ts...> const & it) : l{std::cbegin(it), std::cend(it)}
{ }
int main ()
{
std::list<int> l {1, 2, 3, 4};
A a(l);
for (auto i : a.l)
std::cout << i << " ";
std::cout << std::endl;
A b {{1, 2, 3, 4}};
for (auto i : b.l)
std::cout << i << " ";
std::cout << std::endl;
}