c++:可以在不知道std::_Container_base是map还是vector的情况下处理它吗?
c++: can i process std::_Container_base without knowing if it is a map or a vector?
猜我有
class C1 : public B { /*...*/ };
class C2 : public B { /*...*/ };
std::map<std::string, C1> myMap;
std::vector<C2> myVector;
是否有一种方法(以及语法)来调用函数foo…
- 只需要处理B 的功能
- 只需要在地图和矢量的所有元素上处理它们,而不关心它们是如何组织的?
std::vector
和std::map
都是std::_Container_base
的,但我不知道如何编写(伪代码)的语法:
void foo(std::_Container_base-of-Bs)
编辑:这是_Container_base
,不是_Tee
c++的方法是使用模板和迭代器。
template <typename ForwardIterator>
void process_bs(ForwardIterator first, ForwardIterator last) {
std::for_each(first, last, [](B& b) {
// do something to b here
});
}
对于vector、list、deque和set,可以使用begin和end简单地调用:
process_bs(v.begin(), v.end());
对于map,元素类型是pair<const Key, Value>
,因此必须调整迭代器。您可以在Boost中使用它。范围,例如:
#include <boost/range/adaptor/map.hpp>
auto values = m | boost::adaptors::map_values;
process_bs(values.begin(), values.end());
EDIT:以下是对变通方法的调查,而实际问题并未在其中得到回答。所以这就是答案:我不知道是否可以处理std::_Container_base
而不知道它是映射还是向量。
我在网上找不到任何关于std::_Container_base
的合理的东西,特别是没有c++标准的东西,所以我猜它源于一个特定的编译器实现。
vector
和map
是完全不同的存储方案。我建议您不要在同一上下文中通用地使用它们。也就是说,从一开始你就可以编写函数模板
template<typename T> foo(T&& t) { /* takes a vector and a map */ }
,但至少当你访问operator[]
时,它们的行为会有所不同。这样既不直观,又容易出错。
然而,这并不意味着你不能把这两种方法结合起来——在size()
、operator[](int)
和可能的其他东西上抽象,比如一些插入机制。
例如,在我最近的一些代码中,我有vector
-存储方案(在底层使用std::vector
),以及一个分段常量向量(使用std::map
)。如果您想这样做,您可以从一个公共基类
template<typename T>
struct ContainerBase
{
virtual int size() const = 0;
virtual T operator[](int) const = 0;
virtual void insert(int, T) = 0; //if required
};
,然后在派生类Vector
和Map
中设置所需的功能。
template<typename T>
struct Vector
{
virtual T operator[](int i) const { return _v[i]; }
virtual T size() const { return _v.size(); }
// ... insert and so on
std::vector<T> _v;
};
template<typename T>
struct Map
{
virtual T operator[](int i) const
{
return *std::lower_bound(i); //add further checks if nothing is found
}
virtual T size() const { return _v.rbegin()->first; // return highest index }
// ... insert and so on
std::map<int, T> _v;
};
Map
的实现只是一个草图。你应该选择一些合理的行为。
这样,很容易设置一个函数foo(ContainerBase&)
,它适用于Vector
和Map
。
要在foo
函数中透明地使用B
子类,您可以这样做:
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <utility>
struct B{
int b_member;
};
class C1 : public B { /*...*/ };
class C2 : public B { /*...*/ };
std::map<std::string, C1> myMap;
std::vector<C2> myVector;
// all the magic is into get_B specializations
template<typename E, typename std::enable_if<std::is_base_of<B, E>::value>::type* a = nullptr>
B& get_B(E& elem)
{
return elem;
}
template<typename E, typename std::enable_if<std::is_base_of<B, typename E::second_type>::value>::type* a = nullptr>
B& get_B(E& elem)
{
return elem.second;
}
// foo can call get_B to hide implementation details of the container
template<typename T>
void foo( T& container)
{
for(auto& elem : container)
{
std::cout << get_B(elem).b_member << 'n';
}
}
int main()
{
myVector.resize(10);
myMap["one"] = {};
foo(myMap);
foo(myVector);
}
由于SFINAE, foo
使用get_B的正确专门化来获取对想要处理的B
子类的引用。
- 在没有太多条件句的情况下,我如何避免被零除
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 在未初始化映射的情况下,将值插入到映射的映射中
- 是默认情况下分配给char数组常量的值
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- 如何在不产生任何垃圾的情况下获得C中的像素
- 在已经使用Git的情况下减少编译时间
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 如何在没有信号的情况下从C++执行QML插槽
- 如何在不知道向量大小的情况下输入向量内部的向量?
- 为什么在某些情况下不写入此文件?
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 在这种情况下,我真的复制了字节还是复制了字符?
- 在这种情况下,将数据存储在诸如SQLite之类的数据库中,还是存储在平面文本文件中更好
- 在这种情况下,我应该使用unique_ptr还是shared_ptr
- 默认情况下全局变量是 extern 还是等效于在全局中使用 extern 声明变量
- 我应该在我的特殊情况下使用矢量还是设置?或者完全不同的东西
- std::of流默认情况下是截断还是附加
- 在这种情况下需要记忆障碍还是只是一种波动
- c++:可以在不知道std::_Container_base是map还是vector的情况下处理它吗?