当包含在另一个向量中时,如何使用矢量包装程序类
How can I use a vector wrapper class when enclosed in another vector?
考虑从第三部分库中的免费功能,该库期望std::vector
作为参数:void foo( std::vector<sometype>& );
现在,我围绕此类型编写包装器,以便可以添加成员功能。为了能够将foo()
与该类型一起使用,我添加了一个访问功能。
class Wrapper
{
private:
std::vector<sometype> _data;
public:
std::vector<sometype>& data() { return _data; }
const std::vector<sometype>& data() const { return _data; }
//... other stuff
};
这样,我仍然可以使用foo()
:
Wrapper a;
foo( a.data() );
但是现在考虑另一个功能,它期望sometype
的向量向量( edit:它将元素添加到该矢量):
void bar( std::vector<std::vector<sometype>>& );
但是我拥有的数据类型是std::vector<Wrapper> vec;
是否有任何方法可以使用我的包装器类型来调用bar()
?我想做的是:
std::vector<Wrapper> vec;
bar( ??? );
我要避免的点是首先使用所需类型的bar()
,然后必须一个一个一个一个一个将元素复制到我的vector<Wrapper>
中。
起初,我会说"不",但也许有一些明智的解决方案?
edit2 :要举一个示例,请使用int
的CC_11 root DataType考虑以下玩具实现:
void bar( std::vector<std::vector<int>>& vv )
{
std::vector<int> v1 = { 1,2,3 };
std::vector<int> v2 = { 4,5,6 };
vv.push_back(v1);
vv.push_back(v2);
}
[在需要在bar函数中添加元素的新注释后编辑] 一种可能的解决方案是保留std::vector<std::vector<sometype>>
以供使用函数,并仅在VectorAccessor
对象上操作引用
#include <iostream>
#include <vector>
struct sometype {
int value;
sometype(int v) : value(v) {}
};
void bar(std::vector<std::vector<sometype>>& par) {
std::cout << "bar() - Before adding new elements:" << std::endl;
for (auto& subvec : par) {
std::cout << "Subvector: {";
for (auto& sometypeItem : subvec) {
std::cout << sometypeItem.value << " ";
}
std::cout << "};" << std::endl;
}
std::vector<sometype> newItem = {32, 33};
par.emplace_back(newItem);
}
class VectorAccessor {
std::vector<std::vector<sometype>>& m_vec;
public:
VectorAccessor(std::vector<std::vector<sometype>>& v) : m_vec(v) {}
template<typename V>
void addVector(V&& vec) {
static_assert(std::is_same<typename std::remove_reference<V>::type,
std::vector<sometype>>::value, "Not the right type");
m_vec.emplace_back(std::forward<V>(vec));
}
std::vector<sometype> accessVector(size_t index) {
return m_vec[index];
}
};
int main(int argc, char ** argv)
{
std::vector<std::vector<sometype>> vec;
VectorAccessor vAcc(vec);
// Add an element through the vector accessor
std::vector<sometype> firstVector = {42};
firstVector.emplace_back(52);
vAcc.addVector(firstVector);
// Call bar and add a few elements
bar(vec);
// Now access stuff with the usual wrapper
std::cout << "Elements added by bar:" << std::endl;
std::cout << "Subvector: {";
for (auto& sometypeItem : vAcc.accessVector(1)) {
std::cout << sometypeItem.value << " ";
}
std::cout << "};" << std::endl;
return 0;
}
示例
开箱即用,呼叫 vector<vector<something>
的函数无法使用vector<Wrapper>
,因为它们的类型是不同的,并且编译器明确期望前者。
我认为这种类型替代的任何方式都无法在C 中起作用。
解决方案
每个人都有解决方法:您可以使用自己的代码中的转换使魔术发生。
让我解释。
如果您打算使用的功能以vector<vector<something>>
为CC ,则您基本上必须给它一个vector<vector<something>>
。因此,您不能将矢量作为vector<Wrapper>
创建,并避免将其转换为vector<vector<something>>
。
另一方面,您可以
- 使用
vector<vector<something>
,您将在其中推动Wrapper
的实例(使用隐式转换)。 - 如果您需要
Wrapper
函数性,则可以使用转换构造函数转换vector<something>
。
让我们以这个例子:
#include <iostream>
#include <vector>
using namespace std;
//Templated class wrapper. It does not have to be templated though.
template<typename T>
class Wrapper{
private:
//Here is our inner vector.
vector<T> vect;
public:
//here is our implicit convertion operator :
operator vector<T>& () const {return this->vect;}
//A function so that we can push some stuff in it
void push(T elem){
this->vect.push_back(elem);
}
//here is some additional functionnality in top of vector;
void print(){
int i = 0;
for(i=0;i<this->vect.size();i++){
cout << vect[i] << " ";
}
cout << endl;
}
//this is our very simple conversion constructor
Wrapper<T>(vector<T> vect){
this->vect = vect;
}
//we still need a normal constructor
Wrapper<T>(){}
};
//A function that takes a vector of vectors.
vector<int> concat(vector<vector<int>> vectors){
int i = 0,j=0;
vector<int> result;
for(i=0;i<vectors.size();i++){
for(j=0;j<vectors[i].size();j++){
result.push_back(vectors[i][j]);
}
}
return result;
}
int main()
{
//Let's create an instance of Wrapper and fill it.
Wrapper<int>ex;
ex.push(1);
ex.push(2);
//And yet another one
Wrapper<int>ex2;
ex2.push(5);
ex2.push(6);
//Here we create precisely what the 'concat' function wants:
//namely a vector<vector<int>>.
vector<vector<int>> vectors;
//you can push Wrappers in it, since the conversion will take place.
vectors.push_back(ex);
vectors.push_back(ex2);
//this function call will be successful, since the type of
//vectors is vector<vector<int>>
vector<int> res = concat(vectors);
//Now if you want to use the wrapper functionnality on any
//vector<int>, just convert it on-demand.
//The constructor is extra light-weight in terms of computing power
//as you can see above.
Wrapper<int>(res).print();
Wrapper<int>(vectors[0]).print();
}
P.S。
push_back
功能将复制该元素,因此,如果您的函数确实修改了您的向量,则不会在包装器上反映它,因为它是已修改的内部向量的副本。使用真实的vector<something>
和push_back
会导致相同的行为。
而不是 std::vector<Wrapper> vec;
使用
std::vector< std::vector<sometype> > vec;
无论如何,您可以将包装器对象插入VEC
vec.push_back(a.data());
,然后致电bar(vec);
好的,所以我想出了一些似乎有效的东西,尽管可能还有一些问题。这个想法是将向量的向量包装到某些全局包装器中,然后使用指针访问其内部数据的初始包装器。
用以下玩具bar()
函数说:
void bar(std::vector<std::vector<int>>& par)
{
std::vector<int> v1 = { 1,2,3 };
par.push_back(v1);
}
两个包装纸:
struct GlobalWrapper
{
std::vector<std::vector<int>> _data;
size_t size() const { return _data.size(); }
std::vector<int>& Get( size_t i ) { return _data[i]; }
const std::vector<int>& Get( size_t i ) const { return _data[i]; }
};
struct Wrapper
{
std::vector<int>* _data;
void DoSomething() const
{
cout << "values: ";
std::copy( _data->begin(), _data->end(), std::ostream_iterator<int>(std::cout, " "));
}
Wrapper( std::vector<int>& value ) : _data(&value)
{
}
};
和一个测试程序:
int main(int argc, char ** argv)
{
GlobalWrapper gw;
cout << "size before=" << gw.size() << endl;
bar( gw._data );
cout << "size after=" << gw.size() << endl;
Wrapper w = gw.Get(0); // get first element and do something with it
w.DoSomething();
return 0;
}
剩下的一个问题:数据所有权。可能需要一些明智的指针。
运行代码在这里。
- 如何包装第三方DLL在R中使用
- 使用 Python Extension API 包装复杂C++类
- 使用运算符*重载包装矩阵乘法
- 错误:"释放后使用包装器对象 (WRAPPER_ESCAPE)"
- 将 std::vector<double> 从 C++ 包装到 C 以在 Swift 中使用
- 使用 pybind11 包装 yaml-cpp 迭代器
- 使用双包装器类进行位操作(C++、clang)修复性能下降问题
- "Cannot convert Python object argument to type '<typename>'" - 使用 Cython 包装 C++ 类时出错
- 在 C# .NET 项目中使用 C++ 包装器
- C# 使用包装类中的字符串参数调用 C++ 方法
- 如何从c#中的托管c++dll(使用包装类)获取字符串
- OpenCL 1.1 使用C++包装器的未定义引用
- OpenCL:如何使用C++包装器检查构建错误
- 如何使用包装类中定义的__declspec(dllexport)结构进行导出
- 为已经存在的注册表类使用包装类是一种好方法吗?
- 在c++中使用包装的整数作为索引
- 在Node.js和v8中调用一个使用包装对象作为参数的函数
- 使用c++包装器的OpenCL -如何转换cl::CommandQueue到cl_command_queue
- 使用包装器类作为指向其包装的类型的指针
- 在Java应用程序中使用c#包装器和C API时出现异常