Как создать функцию, которая добавляет содержимое одной коллекции в другую, используя, если возможно, back_inserter для эффективности?
Я полагаю, вы можете объявить функцию шаблона, которая возвращает std::true_type
когда есть push_back()
template <typename T>
constexpr auto hasPushBack (int)
-> decltype( std::declval<T>().push_back(*(std::declval<T>().begin())),
std::true_type() );
и функция возврата при сбое, которая возвращает std::false_type
template <typename>
constexpr std::false_type hasPushBack (long);
, чтобы вы могли изменить свои функции следующим образом
template<typename CIn, typename COut>
typename std::enable_if<true == decltype(hasPushBack<COut>(0))::value>::type
addAll (CIn && from, COut && to)
{ std::copy(std::begin(from), std::end(from), std::back_inserter(to)); }
template<typename CIn, typename COut>
typename std::enable_if<false == decltype(hasPushBack<COut>(0))::value>::type
addAll(CIn && from, COut && to)
{ std::copy(std::begin(from), std::end(from), std::inserter(to, to.begin())); }
Если вы можете использовать C ++ 14 или новее, вы также можете определить переменную шаблона со значением
template <typename T>
constexpr bool hasPushBack_v = decltype(hasPushBack<T>(0))::value;
, и вы можете упростить функции следующим образом:
template<typename CIn, typename COut>
std::enable_if_t<true == hasPushBack_v<COut>>
addAll (CIn && from, COut && to)
{ std::copy(std::begin(from), std::end(from), std::back_inserter(to)); }
template<typename CIn, typename COut>
std::enable_if_t<false == hasPushBack_v<COut>>
addAll(CIn && from, COut && to)
{ std::copy(std::begin(from), std::end(from), std::inserter(to, to.begin())); }