Functors in static global arrays - c++

I've been trying to figure out how to properly pair a function with an id. What I've been doing so far is a C-way of doing it:
#include <iostream>
void PrintA();
void PrintB();
struct Function
{
int id;
void (*function)();
};
static const Function functions[] =
{
{1, PrintA},
{2, PrintB},
{0, 0}
};
void PrintA()
{
std::cout << "A" << std::endl;
};
void PrintB()
{
std::cout << "B" << std::endl;
};
int main()
{
int id = 1;
for(int i = 0; functions[i].function != 0 ; i++)
{
if(functions[i].id == id)
{
functions[i].function();
}
}
}
I'm trying to achieve the same functionality using functors in C++. I suppose I need to use inheritance to be able to store the different functions in the same array meaning I also need to use pointers for the array in order to prevent slicing. Is the following way of doing this the correct way and are there any alternatives?
Also is there any simpler version to call the operator than how I did it?
#include <iostream>
#include <memory>
class Base
{
public:
virtual void operator()() = 0;
};
class PrintA : public Base
{
public:
void operator()();
};
void PrintA::operator()()
{
std::cout << "A" << std::endl;
}
class PrintB : public Base
{
public:
void operator()();
};
void PrintB::operator()()
{
std::cout << "B" << std::endl;
}
struct Functor
{
int id;
std::shared_ptr<Base> function;
};
static Functor functors[] =
{
{1, std::shared_ptr<Base>(new PrintA)},
{2, std::shared_ptr<Base>(new PrintB)},
{0, 0}
};
int main()
{
int id = 2;
for(int i = 0; functors[i].function != 0 ; i++)
{
if(functors[i].id == id)
{
functors[i].function->operator()();
}
}
}
EDIT: I have to use a rather old GCC version making it impossible to use c++11 features. Boost is available, though. I suppose an std::map would be a good idea, but what I was really asking (didn't really make it clear) was that is there a better way to store the functions than shared_ptr. I suppose that std::function/boost::function way is the way to do it.

In C++11 (or Boost, if you're stuck in the past), this kind of type erasure is available in the function wrapper; and there's always been map to perform the ID-based lookup. So your example is as simple as:
#include <map>
#include <functional>
#include <iostream>
// Note: This will be a lot messier if you're stuck with a pre-2011 compiler.
// You'll need to define the functors (or functions) separately, and either
// initialise the map with the result of a function call (possibly using
// Boost.Assign), or write some code somewhere else to populate it.
//
// Or use an array, with lookup code like your C implementation.
std::map<int, std::function<void()>> functors {
{1, [](){std::cout << "A" << std::endl;}},
{2, [](){std::cout << "B" << std::endl;}}
};
int main() {
functors[2]();
}
As noted in the comments, if the real situation is as simple as the example, you could use a function pointer rather than function (and still initialise it with a lambda, if you like), and an array (indexed by id) rather than a map. My example assumes that you want a more general solution, mapping arbitrary values to arbitrary functors.

Simple:
#include <functional>
#include <iostream>
#include <vector>
void sayA() { std::cout << "A" << std::endl; }
void sayB() { std::cout << "B" << std::endl; }
struct Foo
{
explicit Foo(int i) : i_(i) {}
void operator()() const { std::cout << "foo " << i_<< "!" << std::endl; }
int i_;
};
std::vector<std::function<void()>> funcs{ sayA, sayB, Foo(42) };
int main()
{
for (const auto& f : funcs) f();
}

Related

How can I create an array of member function pointers coupled with different objects?

Say I have class A with function foo(int i) and class B with function bar(int i), as well as objectA (of class A) and objectB (of class B). I can call the functions like so
objectA.foo(10);
objectB.bar(20);
What I would like to do is have them both as function pointers in an array arr and calling them like so
arr[0](10);
arr[1](20);
Is there a way of doing this in C++? If so, how efficient is it?
You could store std::function objects in a std::vector that you create from lambda functions capturing objectA or objectB. Calling std::function objects comes with a little overhead so if time is critical, you'll have to measure if it's good enough.
Example:
#include <functional>
#include <iostream>
#include <vector>
struct A {
void foo(int x) { std::cout << "A::foo " << x << '\n'; }
};
struct B {
void bar(int x) { std::cout << "B::bar " << x << '\n'; }
};
int main() {
A objectA;
B objectB;
std::vector< std::function<void(int)> > arr{
[&objectA](int x) { objectA.foo(x); },
[&objectB](int x) { objectB.bar(x); },
};
arr[0](10);
arr[1](20);
}
Output:
A::foo 10
B::bar 20
Similar to #ted-lyngmo's answer, but with C++20, you can also use std::bind_front to create the function object for the vector:
int main()
{
A objectA;
B objectB;
std::vector<std::function<void(int)>> arr{
std::bind_front(&A::foo, objectA),
std::bind_front(&B::bar, objectB)
};
arr[0](10);
arr[1](20);
}
Godbolt

How to store methods as function pointers in a map container?

I want to be able to call functions based on the data I read from file.
So for each item type, I want to call the desired reader method.
I wrote this code, but it does not compile where I want to add function pointers to the map. What is wrong?
#include <vector>
#include <map>
#include <iostream>
class reader
{
std::map< std::string, void(*)()> functionCallMap; // function pointer
void readA(){ std::cout << "reading A\n";};
void readB(){ std::cout << "reading B\n";};;
public:
reader()
{
*functionCallMap["A"] = &reader::readA;*
*functionCallMap["B"] = &reader::readB;*
}
void read()
{
auto (*f) = functionCallMap["A"];
(*f)();
}
};
I am filling the map at Constructor.
You can use std::function with a lambda or std::bind :
class reader
{
std::map<std::string, std::function<void()>> functionCallMap;
void readA() { std::cout << "reading A\n"; };
void readB() { std::cout << "reading B\n"; };
public:
reader()
{
functionCallMap["A"] = [this]() { readA(); };
functionCallMap["B"] = std::bind(&reader::readB, this);
}
void read()
{
functionCallMap["A"]();
functionCallMap["B"]();
}
};
You need to use pointers to member functions, like this:
class reader
{
using FuncPtr = void(reader::*)(); // function pointer
std::map< std::string, FuncPtr> functionCallMap;
void readA(){ std::cout << "reading A\n"; }
void readB(){ std::cout << "reading B\n"; }
public:
reader()
{
functionCallMap["A"] = &reader::readA;
functionCallMap["B"] = &reader::readB;
}
void read()
{
auto f = functionCallMap["A"];
(this->*f)();
}
};
int main()
{
reader r;
r.read();
}
There are two answers so far, this and this.
The obvious difference is that one uses std::function and other uses function pointers. This is not the important difference!!
The key point is that the member functions are non-static member functions. So, they are not of type void().
They are of type void(reader::*)(). Thus, they can be only called if an object of type is reader is given; one can understand this somewhat as a hidden parameter.
The first answer just fixes the problem by specifying the correct type. This can be done using function pointers (as presented) or using std::function (The latter is much more expensive!).
The second answer fixes the problem by binding the function pointer to the particular instance of the class. After binding, the type is then indeed void(). This cannot be done using raw function pointers (because they can only point to a function and not an object/function pair!).
I ended up with this solution. It does the job, but I have some doubts over its aesthetics. Anyway, to sum up, I ended up with this code:
#include <map>
#include <iostream>
#include <functional>
class reader
{
std::map< std::string, std::function<void(std::string tableName)>> functionCallMap; // function pointer
void readA(const std::string tableName){ std::cout << "reading:" << tableName<< "\n"; }
void readB(const std::string tableName){ std::cout << "reading:" << tableName <<"\n"; }
public:
reader()
{
functionCallMap["A"] = std::bind(&reader::readA, this, std::placeholders::_1);
functionCallMap["B"] = std::bind(&reader::readA, this, std::placeholders::_1);
}
void read()
{
const std::string table_name = "A";
functionCallMap[table_name](table_name);
}
};
int main()
{
reader r;
r.read();
}
I pass the table name to the reader, it is nicely done with the bind and placeholder.

C++: How to store various member functions of different classes for later use

thanks in advance for your support.
I'm using C++11 and I want to store public member functions of some classes for later use as callback functions; e.g. I want to store some functions that matches this template: void(classname::*)(void). As far as I know, I have to store their objects too, It's fine. For example:
// PSEUDO CODE
class A {
public:
void myfunc() {}
}myobj;
class B {
public:
void myfunc2() {}
}myobj2;
/* storing */
mystorageclass storage;
storage.push(&myobj, &A::myfunc);
storage.push(&myobj2, &B::myfunc2);
/* call them back */
(storage[0].object->*(storage[0].callback))();
(storage[1].object->*(storage[1].callback))();
Is there any safe and generic way to do that? Actually I've found a way, but I'm not sure how much it's portable across processors or compilers.
//test.cpp - compiled with: g++ test.cpp -o test -std=c++11
#include <iostream>
#include <vector>
class A {
public:
void myfunc() { std::cout << "Test A::myfunc()" << std::endl; }
}myobj;
class B {
public:
void myfunc2() { std::cout << "Test B::myfunc2()" << std::endl; }
}myobj2;
struct Callback {
void* object;
void(* method)(void*);
};
std::vector<Callback> callbackList;
template<typename FunctionPtr>
void add(void* object, FunctionPtr fptr) {
Callback cb;
cb.object = object;
cb.method = (void(*)(void*))(*(void**)(&fptr));
callbackList.push_back(cb);
}
int main() {
//add to list for later use
add(&myobj, &A::myfunc);
add(&myobj2, &B::myfunc2);
//call them back
callbackList[0].method(callbackList[0].object);
callbackList[1].method(callbackList[1].object);
}
And another way to do; I feel this is much more safe:
//test2.cpp - compiled with: g++ test2.cpp -o test2 -std=c++11
#include <iostream>
#include <vector>
class A {
public:
void myfunc() { std::cout << "Test A::myfunc()" << std::endl; }
}myobj;
class B {
public:
void myfunc2() { std::cout << "Test B::myfunc2()" << std::endl; }
}myobj2;
struct Callback {
struct A;
A* object;
void(A::* method)();
void call() {
(object->*method)();
}
};
std::vector<Callback> callbackList;
template<typename FunctionPtr>
void add(void* object, FunctionPtr fptr) {
Callback cb;
cb.object = (Callback::A*)object;
cb.method = (void(Callback::A::*)())(fptr);
callbackList.push_back(cb);
}
int main() {
//add to list for later use
add(&myobj, &A::myfunc);
add(&myobj2, &B::myfunc2);
//call them back
callbackList[0].call();
callbackList[1].call();
}
Does these usages are safe? Or what do you suggest instead of these.
Thanks.
Replace Callback with std::function<void()>.
Replace add with
template<class T, class R, class U>
void add(T* object, R(U::*ptr)()) {
Callback cb = [object, ptr]{ object->ptr(); };
callbackList.push_back(cb);
// or just
// callbackList.push_back([object, ptr]{ object->ptr(); });
}
note that this supports passing in pointers-to-parent member functions, and callbacks that do not return void and discarding the result.
std::function stores a generic "call this later". You pass a type compatible with the return value, and args compatible with what you want to call later, in the template signature argument of std::function<signature>. In this case, <void()>.
Problem with the second version
In the line
cb.method = (void(*)(void*))(*(void**)(&fptr));
you are casting a function pointer to void**. I am not sure that is supported by the standard. My guess is it is not. I know casting a function pointer to void* is not supported by the standard. See Print an address of function in C++, g++/clang++ vs vc++ , who is rght? for details.
And then, you proceed to use:
callbackList[1].method(callbackList[1].object);
This relies on conventions used by a compiler to pass this as the first hidden argument when calling a member function of a class. There is no guarantee that the method is used by all compilers. The standard does not explicitly state that.
Problem with the third/last version
You are using:
cb.object = (Callback::A*)object;
cb.method = (void(Callback::A::*)())(fptr);
regardless of whether the object type is A or B. This is cause for undefined behavior. The standard does not support casting of an object pointer to any old pointer type.
A Cleaner Version
Use a base class for Callback.
struct Callback {
virtual ~Callback() = 0;
virtual void call() = 0;
};
Then, use a class template for the real Callbacks.
template <typename T>
struct RealCallback : public Callback
{
RealCallback(T* obj, void (T::*m)(void)) : object(obj), method(m) {}
virtual void call()
{
(object->*method)();
}
T* object;
void (T::*method)();
};
With this, you won't be able to store a list of Callback objects but you can store a list of shared_ptr<Callback>s.
std::vector<std::shared_ptr<Callback>> callbackList;
Here's a complete program that does not rely on any ugly casts and works perfectly.
//test.cpp - compiled with: g++ test.cpp -o test -std=c++11
#include <iostream>
#include <vector>
#include <memory>
class A {
public:
void myfunc() { std::cout << "Test A::myfunc() on " << this << std::endl; }
}myobj;
class B {
public:
void myfunc2() { std::cout << "Test B::myfunc2() on " << this << std::endl; }
}myobj2;
struct Callback {
virtual void call() = 0;
};
template <typename T>
struct RealCallback : public Callback
{
RealCallback(T* obj, void (T::*m)(void)) : object(obj), method(m) {}
virtual void call()
{
(object->*method)();
}
T* object;
void (T::*method)();
};
std::vector<std::shared_ptr<Callback>> callbackList;
template<typename T>
void add(T* object, void (T::*fptr)()) {
RealCallback<T>* cb = new RealCallback<T>(object, fptr);
callbackList.push_back(std::shared_ptr<Callback>(cb));
}
int main() {
//add to list for later use
add(&myobj, &A::myfunc);
add(&myobj2, &B::myfunc2);
std::cout << "myobj: " << &myobj << std::endl;
std::cout << "myobj2: " << &myobj2 << std::endl;
//call them back
callbackList[0]->call();
callbackList[1]->call();
}
Update, in response to comment by Yakk
I think Yakk's suggestion makes sense. You can remove the classes Callback and RealCallback with
using Callback = std::function<void()>;
std::vector<Callback> callbackList;
Then, add can be simplified to:
template<class T>
void add(T* object, void(T::*ptr)()) {
callbackList.push_back([object, ptr]{ (object->*ptr)();});
}
With those changes, main needs to be slightly updated to:
int main() {
//add to list for later use
add(&myobj, &A::myfunc);
add(&myobj2, &B::myfunc2);
std::cout << "myobj: " << &myobj << std::endl;
std::cout << "myobj2: " << &myobj2 << std::endl;
// Updated. Can't use callbackList[0]->call();
//call them back
callbackList[0]();
callbackList[1]();
}
Try with std::function or std::bindboth of them need to keep the reference to the instance:
#include <string>
#include <iostream>
#include <functional>
using namespace std;
class MyClass
{
int _value;
public:
MyClass(int value)
{
_value = value;
}
void food()
{
cout << "Foo is doing something whit value: " << _value << endl;
}
void bar()
{
cout << "Bar is doing something whit value: " << _value << endl;
}
};
int main()
{
MyClass* c1 = new MyClass(1);
MyClass* c2 = new MyClass(2);
cout << "Using 'std::function':" << endl;
std::function<void(MyClass&)> food = &MyClass::food;
std::function<void(MyClass&)> bar = &MyClass::bar;
food(*c1);
bar(*c1);
food(*c2);
bar(*c2);
cout << "Using 'std::bind':" << endl;
auto foodBind = std::bind(&MyClass::food, std::placeholders::_1);
auto barBind = std::bind(&MyClass::bar, std::placeholders::_1);
foodBind(*c1);
barBind(*c1);
foodBind(*c2);
barBind(*c2);
system("PAUSE");
};
the Output is:

Cast between two slightly different std::map

I have a std::map defined as follows:
typedef void (SomeClass::*callback_f)();
typedef std::pair<std::string, callback_f> my_pair;
typedef std::map<char,my_pair> my_map1;
There are multiple of these definitions, so there is my_map1, my_map2, etc. and every one of them differs from the other for the class SomeClass, which is SomeClass, SomeClassTwo, etc.
My need is to pass all these maps to a single function, which must have a single signature regardless of the maps, so I defined a generic map:
typedef std::pair<std::string ,void(*)(void)> my_generic_pair;
typedef std::map<char, my_generic_pair> my_generic_map;
And a function which takes it as a parameter:
void myGenericFunction(my_generic_map lmap);
myGenericFunction doesn't really use the callback, but uses the other two values from the my_map{$i}, i=1...n.
The problem is no matter how hard I try to cast between the two maps, the compiler (C++11 compliant GCC) always complains.
Any ideas would be very much appreciated.
If you need to pass all the maps to a single function, then all the maps must be exactly the same type (but you already knew that).
A little re-engineering should give you what you want.
Rather than define your map to hold a specific function pointer signature, simply define one map type that holds a polymorphic callable object - such an object is the std::function<>.
full compilable example (remember to enable c++11):
#include <iostream>
#include <functional>
#include <utility>
#include <string>
#include <map>
// callback_f is any callable that takes no parameters
typedef std::function<void()> callback_f;
typedef std::pair<std::string, callback_f> my_pair;
typedef std::map<char,my_pair> universal_map;
using namespace std;
struct SomeClass {
static void callme_for_all() {
cout << "SomeClass Hears You";
}
};
struct SomeOtherClass {
SomeOtherClass(string name)
: _name { move(name) }
{}
void callme_for_each() const {
cout << "I am called " << _name;
}
private:
string _name;
};
void handle_map(const universal_map& m) {
for (const auto& item : m) {
cout << item.first << ":" << item.second.first << ":";
item.second.second();
cout << endl;
}
}
int main()
{
cout << "Hello World" << endl;
SomeClass a,b,c;
SomeOtherClass x { "x" }, y { "y" }, z { "z" };
universal_map map_someclass {
{ 'A', { "chicken", std::bind(&SomeClass::callme_for_all) } },
{ 'B', { "donkey", std::bind(&SomeClass::callme_for_all) } },
{ 'C', { "turkey", std::bind(&SomeClass::callme_for_all) } },
};
universal_map map_someotherclass {
{ 'A', { "pig", std::bind(&SomeOtherClass::callme_for_each, &x) } },
{ 'B', { "cat", std::bind(&SomeOtherClass::callme_for_each, &y) } },
{ 'C', { "dog", std::bind(&SomeOtherClass::callme_for_each, &z) } },
};
cout << "map for SomeClass - calling static methods" << endl;
handle_map(map_someclass);
cout << endl;
cout << "map for SomeOtherClass - calling instance methods" << endl;
handle_map(map_someotherclass);
return 0;
}
If you have control on your SomeClass, SomeClass2..., you can use inheritance to solve this problem:
class BaseClass
{
public:
virtual ~BaseClass(){}
virtual void f() = 0;
};
class SomeClass : public BaseClass {...};
class SomeClass2 : public BaseClass {...};
typedef void (BaseClass::*callback_f)();
....
Solution 1:
template<typename T>
void myGenericFunction(std::map < char, std::pair < std::string, T > > lmap);
Solution 2 (only if you can't use templates and overloading for whatever reason):
enum MapType {MY_MAP1, MY_MAP2, ...};
void myGenericFunction(void* lmap, MapType typeOfLmap)
{
switch(typeOfLmap)
{
case MY_MAP1:
//do something with ((my_map1*)lmap)
break;
...
}
}
EDIT: edited according to #TonyD's suggestion.

How can I use a vector wrapper class when enclosed in another vector?

Consider a free function from a third part library that expects a std::vector as argument: void foo( std::vector<sometype>& );
Now, I write a wrapper around this type so I can add member functions. To be able to use foo() with that type, I add an access function.
class Wrapper
{
private:
std::vector<sometype> _data;
public:
std::vector<sometype>& data() { return _data; }
const std::vector<sometype>& data() const { return _data; }
//... other stuff
};
This way, I can still use foo():
Wrapper a;
foo( a.data() );
But now consider another function, that expects a vector of vectors of sometype (edit: and that adds elements into that vector) :
void bar( std::vector<std::vector<sometype>>& );
But the datatype I have is std::vector<Wrapper> vec;
Is there any way to use my wrapper type to call bar() ?
What I want to do is this:
std::vector<Wrapper> vec;
bar( ??? );
The point I want to avoid is first call bar() with the required type, and then having to copy one by one the elements into my vector<Wrapper>.
At first, I'd say "No", but maybe there is some smart solution ?
Edit2: to give an example, consider the following toy implementation for bar() with an int 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);
}
[Edited after new comments requiring elements added in the bar function]
A possible solution would be to keep a std::vector<std::vector<sometype>> for the function to use and just operate on a VectorAccessor object referring to the real vectors
#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;
}
Example
Out of the box, calling a function taking a vector<vector<something> won't work with a vector<Wrapper>, because their type is different, and the compiler explicitely expects the former.
I don't think there is any way this form of type substitution could work in C++.
Workaround
There's a workaround to everyhting : you could use conversions in your own code to let the magic happen.
Let me explain.
If the function you intend to use takes a vector<vector<something>>, in C++, you basically have to give it a vector<vector<something>>. So you can't create your vector as a vector<Wrapper> and avoid converting it to a vector<vector<something>>.
On the other hand, you can
use a vector<vector<something> in which you will push instances of Wrapper (using an implicit conversion).
if you need Wrapper functionnality, you can convert your vector<something> using a conversion constructor.
Let's take that example :
#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. The push_back function will copy the element, so if your function does modify your vector, it won't be reflected on the Wrapper, since it's a copy of its inner vector that has been modified. Using a real vector<something> and push_back would result in the same behaviour.
instead of std::vector<Wrapper> vec;
use
std::vector< std::vector<sometype> > vec;
anyway, you can insert your Wrapper objects into vec
vec.push_back(a.data());
and then call bar(vec);
Ok, so I came up with something that seems to work, although there could be some issues left. The idea is to wrap the vector of vectors into some global wrapper, and then the initial wrapper accessing the data inside it using pointers.
Say with the following toy bar() function:
void bar(std::vector<std::vector<int>>& par)
{
std::vector<int> v1 = { 1,2,3 };
par.push_back(v1);
}
The two wrappers:
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)
{
}
};
And a test program:
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;
}
One issue left: ownership of data. Probably needs some smart pointers.
Running code is here.