Я написал небольшой шаблон функции, который объединяет разные контейнеры в новый контейнер:
#include <vector>
#include <unordered_set>
#include <string>
#include <iostream>
#include <iterator>
namespace impl
{
template <typename OutIterator, typename Container, typename ...Containers>
void join(OutIterator iterator, const Container& container, const Containers& ...containers)
{
for (const auto& item : container)
*iterator++ = item;
join(iterator, containers...); // gcc and clang cannot resolve this call
}
template <typename OutIterator, typename Container>
void join(OutIterator iterator, const Container& container)
{
for (const auto& item : container)
*iterator++ = item;
}
}
template <typename OutContainer, typename ...Containers>
OutContainer join(const Containers& ...containers)
{
OutContainer container;
auto it = std::inserter(container, container.end());
impl::join(it, containers...);
return container;
}
int main()
{
using namespace std;
vector<string> a = {"one"s, "two"s, "three"s};
unordered_set<string> b = {"four"s, "five"s };
auto res = join<unordered_set<string>>(a, b);
for (auto& i : res)
cout << i << "\n";
return 0;
}
При использовании MSVC (cl.exe) с /std:c++17 код компилируется и работает нормально. Но при компиляции с clang-6.0 или gcc-7.3 выдается ошибка компилятора. т.е. gcc говорит
no matching function for call to 'join(std::insert_iterator<std::unordered_set<std::__cxx11::basic_string<char> > >&)'
Таким образом, очевидно, что функция с этой сигнатурой не определена. Но я не понимаю, почему он пытается вызвать такую функцию. Разве это не должно быть решено так
// in main()
join<unordered_set<string>>(a, b);
unordered_set<string> join(const vector<string>& a, const unordered_set<string>& b);
void impl::join(std::insert_iterator<unordered_set<string>> iterator, const vector<string>& a, const unordered_set<string>& b);
void impl::join(std::insert_iterator<unordered_set<string>> iterator, const unordered_set<string>& b);
Почему gcc пытается создать экземпляр join(std::insert_iterator<std::unordered_set<std::__cxx11::basic_string<char>>>&)
?
Вот пример использования проводника компилятора.
impl
, поэтому они вообще опасны. - person StoryTeller - Unslander Monica   schedule 03.04.2018impl
предназначены для использования только из функции глобальной области видимостиjoin
, которая использует insert_iterator, что означает, что она вставляет в контейнер каждое назначение. - person Timo   schedule 03.04.2018auto it = std::back_inserter(container);
... - person Aconcagua   schedule 03.04.2018back_inserter
, потому что контейнер может быть (как показано в моем примере) чем-то другим, кроме вектора (например, набором), у которого нет функцииpush_back
.back_inserter_iterator
иinsert_iterator
используют разные механики. - person Timo   schedule 03.04.2018template <typename OutContainer, typename Container> void join(std::insert_iterator<OutContainer> i, Container const& c);
;back_inserter
: извините, присматривал за необходимостью большей гибкости... Хотя в других ситуациях могло бы быть неплохо. - person Aconcagua   schedule 03.04.2018