C++泛型插入到std容器中?

pau*_*ulm 3 c++ containers c++11

如果我有以下程序:

#include <vector>
#include <set>

template<class T, class U>
void AddToContainer(T& container, U value)
{
  container.push_back(value);
}

int main(char**, int)
{
   std::vector<int> v;
   AddToContainer(v, 1);

   std::set<int> s;
   AddToContainer(s, 1);

   return 0;
}
Run Code Online (Sandbox Code Playgroud)

如何将容器添加为通用?由于std::set没有一个push_back但只有insert,这将无法编译.

Bar*_*rry 5

你可以使用带有伪参数的表达式SFINAE来检查是否push_back()有效:

template <class C, class V>
auto append(C& container, V&& value, int)
    -> decltype(container.push_back(std::forward<V>(value)), void())
{
    container.push_back(std::forward<V>(value));
}

template <class C, class V>
void append(C& container, V&& value, ...)
{
    container.insert(std::forward<V>(value));
}
Run Code Online (Sandbox Code Playgroud)

您的功能将转发到:

template <class C, class V>
void AddToContainer(C& container, V&& value) {
    append(container, std::forward<V>(value), 0);
}
Run Code Online (Sandbox Code Playgroud)

如果push_back()是有效的表达式,第一个过载将是首选,因为int是一个更好的匹配0...如果push_back()没有一个有效的表达式,那么就只有一种可行的过载.


这实际上是一个好主意是一个单独的问题.


Luc*_*iel 5

我相信所有* C++ 容器(尽管不是像 那样的容器适配器priority_queue)都有一个如下所示的插入版本:

iterator insert(iterator location, T&& value)
Run Code Online (Sandbox Code Playgroud)

对于序列集合,位置为实际位置;对于关联集合(如mapand unordered_map),迭代器是一个“提示”参数(例如,map如果您已经准确地知道元素按排序顺序属于哪里,则有助于快速插入元素)。但是,提供无效提示不会导致任何无效行为,因此 C++ 集合的有效通用插入将是:

template<C, T>
void insert(C& collection, T&& value) {
    collection.insert(collection.end(), std::forward<T>(value));
}
Run Code Online (Sandbox Code Playgroud)

* 好像forward_list是唯一没有这个方法的,有道理。