Я хотел бы написать шаблонную функцию, которая перебирает контейнер std::pair
и возвращает шаблонное значение с обоими типами в паре.Я получил это, чтобы работать для std::map
следующим образом:
template <typename T1, typename T2>
std::pair<std::vector<T1>, std::vector<T2>> unzip(const std::map<T1,T2>& zipped)
{
auto unzipped = std::make_pair(std::vector<T1>(), std::vector<T2>());
for (auto& one_two : zipped)
{
unzipped.first.push_back(one_two.first);
unzipped.second.push_back(one_two.second);
}
return unzipped;
}
Это отлично работает, но ограничивает контейнер до std::map
.Я хотел бы, чтобы это работало для чего-то вроде std::vector<std::pair<T1,T2>>
, поскольку итерация для обоих контейнеров работает одинаково.
Я пытался сделать контейнер шаблоном, изменивАргументы шаблона:
template <typename T1, typename T2, template<typename ... Types> class Container>
std::pair<std::vector<T1>, std::vector<T2>> unzip(const Container<T1,T2>& zipped)
{
//do stuff and return
}
, но в этом случае вычет не выполняется, если не используется std::map
, поскольку std::vector
зависит только от одного типа.Затем я попытался стать более креативным, но компилятор жаловался еще больше:
template <typename PairContainerType>
std::pair<std::vector<typename PairContainerType::value_type::first_type>,
std::vector<typename PairContainerType::value_type::second_type>>
unzip(const PairContainerType& zipped)
{
typedef typename PairContainerType::value_type::first_type T1;
typedef typename PairContainerType::value_type::second_type T2;
//do the same stuff and return
}
Я думаю, что то, что я пытаюсь сделать, должно быть возможным, но я в растерянности.Я использую c++11
, если это имеет значение, хотя, если то, что я хочу, доступно в будущих версиях, я все еще заинтересован в этих решениях.Спасибо.
Обновление: благодаря RiaD я получил следующее для работы с c ++ 11:
template <typename PairContainerType,
typename T1 = typename std::remove_const<typename PairContainerType::value_type::first_type>::type,
typename T2 = typename std::remove_const<typename PairContainerType::value_type::second_type>::type>
std::pair<std::vector<T1>, std::vector<T2>> unzip(const PairContainerType& zipped)
{
//do stuff and return
}
Обратите внимание, что он немного отличается от принятого ответа, так как ониспользует std::remove_const
вместо std::remove_const_t
и в конце необходимо добавить ::type
.
RiaD также указывает, что типы шаблонов T1
и T2
могут быть переопределены любым, кто делаетвызов.Как предполагает Jarod42, это может быть смягчено с помощью некоторой дополнительной типизации, что оставляет меня в окончательном решении c ++ 11:
template <typename PairContainerType>
std::pair<std::vector<typename std::remove_const<typename PairContainerType::value_type::first_type>::type>,
std::vector<typename std::remove_const<typename PairContainerType::value_type::second_type>::type>>
unzip(const PairContainerType& zipped)
{
auto unzipped = std::make_pair(
std::vector<typename std::remove_const<typename PairContainerType::value_type::first_type>::type>(),
std::vector<typename std::remove_const<typename PairContainerType::value_type::second_type>::type>());
for (const auto& one_two : zipped)
{
unzipped.first.push_back(one_two.first);
unzipped.second.push_back(one_two.second);
}
return unzipped;
}
В целом, c ++ 14 и c ++ 17 выглядят довольно привлекательно,Я мог бы сэкономить время с помощью функции auto
return!