I have a structure, e.g.
struct Test
{
std::string a;
std::string b;
std::string c;
};
In another part of project I want to assign value to one od three values in structure( I want to edit it).
It is possible to do something like that:
void foo (std::string newValue, std::string nameOfStructMember)
{
for(auto & it : test) //in another part of project exist std::vector<Test> test;
{
it.nameOfStructMember= newValue;
}
}
And e.g. in main.cpp:
foo("This is my new value", "a");
No, you can't do exactly that. What you want is to resolve the adress of a member at runtime via it's name. This is called reflection and not possible in C++.
However you can do something quite similiar with member pointers.
void foo(const std::string &newValue, std::string Test::*member)
{
for(auto & it : test)
{
it.*member = newValue;
}
}
member essentially holds the offset of some member of Test, such that it.*member will access that member. You can call this function with
foo("This is my new value", &Test::a); //or &Test::b and so on
The main drawback here is obviously, that &Foo::a needs to be known at compile time. But you can easily use a std::unordered_map to map actual member names to member pointers:
std::unordered_map<std::string, std::string Test::*> mapping {
{"a", &Test::a},
// and so on
};
It seems you mean something like the following
#include <iostream>
#include <string>
#include <vector>
struct Test
{
std::string a;
std::string b;
std::string c;
};
void f( std::vector<Test> &v, std::string Test::*p, const char *s )
{
for ( auto &t : v )
{
t.*p = s;
}
}
int main()
{
std::vector<Test> v( 2 );
std::string Test::*p = &Test::a;;
f( v, p, "A" );
p = &Test::b;;
f( v, p, "B" );
p = &Test::c;;
f( v, p, "C" );
for ( const auto &t : v )
{
std::cout << t.a << ' ' << t.b << ' ' << t.c;
std::cout << '\n';
}
}
The program output is
A B C
A B C
Related
I want to be able to store a pointer of a function in a struct or class, then I can call upon that function when a button is pressed? here is what I have:
struct INFO
{
std::function<int(int, int)> call_back;
};
class YO
{
public:
YO() {};
~YO() {};
int SUM(int A, int B) { return A + B; }
};
int main()
{
//std::function<int(int, int)> datFunc = SUM;
INFO info;
YO* yo = new YO();
info.call_back = yo->SUM;
//std::function<int(int, int)> func =;
std::cout << info.call_back(10, 10) << std::endl;
system("pause");
return 0;
}
I get errors:
Error C3867 'YO::SUM': non-standard syntax; use '&' to create a pointer to member FunctionPointertest
Error C2679 binary '=': no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion) FunctionPointertest
You need to also supply an instance of the host object to the function call, in this case of class YO. std::function supports this, amongst many conversions it can do, but then the prototype becomes
std::function<int(YO*, int, int)> call_back;
And when you call it:
info.call_back(&yo, 10, 10)
Some options to do what you want. Using the lambda is the best solution.
void func() {
INFO info;
YO yo;
YO* yo2 = new YO;
info.call_back = [&yo](int a, int b) {
return yo.SUM(a, b);
};
using namespace std::placeholders;
info.call_back = std::bind(&YO::SUM, std::ref(yo), _1, _2);
info.call_back = std::bind(&YO::SUM, yo2, _1, _2);
}
P.S. You don't usually want to use new in c++.
Here are a set of Variadic Template Classes that will enable you to do this with ease if you have C++17 available to you. The first class simply stores a generic version of a std::function of any type! The second class stores the first class through a member function and will register either a function pointer, a function object or a lambda. It also has another member function that will invoke it. I am currently using lambdas in this example. I have two lambdas, the 1st takes two int types adds them and returns an int as in your problem above. The 2nd takes two std::strings concatenates them then prints them to the screen but does not return any value. You can even expand this by having a std::vector<Functor<>> stored in the driver class. The register_callback would change slightly as to pushing them into the vector, and the call_back you have options. You could either call them all in one go, or search via an index value to call a specific one, but I'll leave that as an exercise to you.
#include <string>
#include <iostream>
#include <functional>
template<typename RES_TYPE, typename... ARG_TYPES>
struct Functor {
std::function<RES_TYPE( ARG_TYPES... )> func_;
};
template<typename RES_TYPE, typename... ARG_TYPES>
class Driver {
private:
Functor<RES_TYPE, ARG_TYPES...> functor;
public:
Driver() = default;
~Driver() = default;
void register_callback( const Functor<RES_TYPE, ARG_TYPES...> &func ) {
functor = func;
}
RES_TYPE call_back( ARG_TYPES... args ) {
return functor.func_( std::forward<ARG_TYPES>(args)... );
}
};
int main() {
// Function Type: int ( int, int );
Functor<int, int, int> func;
auto lambda = []( int a, int b ) { return a + b; };
func.func_ = lambda;
Driver<int, int, int> driver;
driver.register_callback( func );
int a = 3;
int b = 5;
std::cout << driver.call_back( a, b ) << '\n';
std::cout << driver.call_back( 7, 5 ) << '\n';
// Function Type: void ( string, string );
Functor<void, std::string, std::string> func2;
auto lambda2 = []( std::string str1, std::string str2 ) {
str1 = str1 + " " + str2;
std::cout << str1 << '\n';
};
Driver <void, std::string, std::string> driver2;
func2.func_ = lambda2;
driver2.register_callback( func2 );
std::string str1 = "Hello";
std::string str2 = "World";
driver2.call_back( str1, str2 );
driver2.call_back( "Generic", "Programming" );
return 0;
}
The output is:
8
12
Hello World
Generic Programming
If you notice with this code here; there is no need to mess with pointers or dynamic memory. This is all taken care of by the use of std::function for us and the default dtors of the classes.
I tried my best to design this with simplicity, readability while making it portable and generic as possible. I am sure there can be some improvements made, but I think this is in line of what you are asking for.
In the code below the initializer list is initialized with a B and a C object whose ctors pass in values “bbb” and 333 respectively. Since these objects derive from A, the list properly creates two A elements.
#include <string>
#include <vector>
#include <iostream>
struct A
{
char ch;
};
struct B : A
{
B( std::string str ) : str( str ) {}
std::string str;
};
struct C : A
{
C( int num ) : num( num ) {}
int num;
};
struct D
{
D( std::initializer_list< A* > initializerList )
: variadicVect( initializerList )
{}
std::vector< A* > variadicVect;
};
int main()
{
D d { new B { "bbb" }, new C { 333 } };
d.variadicVect[ 0 ]->ch = 'm'; // ok, but accesses base member
//std::cout << d.variadicVect[ 0 ]->str << std::endl; // error C2039: 'str': is not a member of 'A'
//std::cout << d.variadicVect[ 1 ]->num << std::endl; // error C2039: 'num': is not a member of 'A'
return 0;
}
A similar problem was reported in link resolved by #Jarod42. He identified Object Slicing as the problem. To avoid this assignment-by-value issue, I new’d the initializer list object, but am still unable to access the derived class.
Another attempt I tried was to templatize the initializer_list type (code not shown), but I got this error: ‘D::variadicVect': only static data member templates are allowed’
My goal is to be able to initialize the list with various derived objects choosing the derived type at compile time and yet be able to access them properly at runtime. Is that possible?
To make your code compile you would have to cast your vector elements to appropriate types:
std::cout << static_cast<B*>(d.variadicVect[ 0 ])->str << std::endl;
std::cout << static_cast<C*>(d.variadicVect[ 1 ])->num << std::endl;
otherwise C++ sees them as type A and only interface from A is available.
Other solution is to add virtual functions (virtual std::string Str(){return "";} and virtual int Num(){return 0;} ) to A and override them in base classes, where needed. Then you will not have to cast. example below:
http://coliru.stacked-crooked.com/a/ed7c73a5d8afa5e9
#include <string>
#include <vector>
#include <iostream>
struct A
{
char ch;
virtual std::string Str() { return ""; }
virtual int Num() { return 0; }
};
struct B : A
{
B( std::string str ) : str( str ) {}
std::string str;
std::string Str() override { return str; }
};
struct C : A
{
C( int num ) : num( num ) {}
int num;
int Num() override { return num; }
};
struct D
{
D( std::initializer_list< A* > initializerList )
: variadicVect( initializerList )
{}
std::vector< A* > variadicVect;
};
int main()
{
D d { new B { "bbb" }, new C { 333 } };
d.variadicVect[ 0 ]->ch = 'm'; // ok, but accesses base member
std::cout << d.variadicVect[ 0 ]->Str() << std::endl;
std::cout << d.variadicVect[ 1 ]->Num() << std::endl;
return 0;
}
This question was neatly implicitly answered in another one of my postings (see its Edit section for my explanation of why it took so long for me to figure out what the right question was, after which the solution - union-like classes - was just a matter of getting the constructors and destructors right): using a union-like class in an std::initializer_list.
How does one pass and operate on constant (or non constant) references inside STL containers. Say I have a function:
bool foo(const Obj& A, const Obj& B) {
// do some computation on A & B
}
and since A & B always occur together, I would like to put them in an STL pair:
bool foo(const std::pair<Obj, Obj>& A_and_B) {
// do some computation on A & B
}
However now both objects A & B get copied into a pair every time foo needs to be called. Looking around I found reference_wrapper in C++11. Though doing something like this doesn't quite work:
bool foo(const std::pair<std::reference_wrapper<Obj>, std::reference_wrapper<Obj>>& A_and_B) {
// do some computation on A & B
}
bool foo(const std::pair<Obj, Obj>& A_and_B) {
foo(std::make_pair(std::ref(A_and_B.first), std::ref(A_and_B.second)));
}
What is the correct way of passing containers with reference values without using pointers?
To avoid copy when make_pair, why not define the pair as std::pair<Obj&, Obj&> directly?
#include <iostream>
#include <string>
#include <functional>
class Obj
{
};
bool foo(const std::pair<Obj, Obj>& A_and_B) {
// do some computation on A & B
std::cout << __func__ << std::endl;
}
bool foo(const std::pair<Obj&, Obj&>& A_and_B) {
// do some computation on A & B
std::cout << "ref version foo" << std::endl;
}
int main( void )
{
Obj A;
Obj B;
foo( std::make_pair(std::ref(A), std::ref(B)) );
return 0;
}
Here's one way, passing just a pair of references (no copying):
#include <utility> // pair
#include <functional> // ref
#include <iostream>
using namespace std;
struct Obj {};
auto foo( pair<Obj const&, Obj const&> const ab )
{
Obj const& a = ab.first;
Obj const& b = ab.second;
cout << &a << " " << &b << endl;
}
auto main() -> int
{
Obj a;
Obj b;
cout << &a << " " << &b << endl;
foo( make_pair( ref( a ), ref( b ) ) );
}
This works nicely because std::make_pair has special support for std::reference_wrapper arguments, then deducing reference to the referred to type.
std::reference_wrapper is the result type of std::ref.
Since std::make_pair supports move semantics, you just need to write your function as you suggested, but when calling it move objects A and B into the std::make_pair as shown below:
// Just as you already suggested
bool foo(const std::pair<Obj, Obj>& A_and_B) {
// do some computation on A & B
}
Call it as:
int main( void )
{
Obj A; // work on A
Obj B; // work on B
auto A_and_B = std::make_pair(std::move(A), std::move(B)); // effectively moves A and B; no copies!
// A and B are now reset, but you can use A_and_B.first and A_and_B.second!
foo( A_and_B );
return 0;
}
Live demo.
Since you are passing the pair by reference, it is not copied. However, Obj A=A_and_B.first will create a copy. If you want to avoid that, you can get a reference to the element, i.e.
Obj &A=A_and_B.first.
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.
Trying to reproduce something that in C# you would do something like this:
string FormatString(params object[] args) {
return string.Format(CultureInfo.InvariantCulture, args);
}
And in Obj-c it would look like this:
#include <stdarg.h>
void logObjects(id firstObject, ...) {
va_list args;
va_start(args, firstObject);
id obj;
for (obj = firstObject; obj != nil; obj = va_arg(args, id))
NSLog(#"%#", obj);
va_end(args);
}
logObjects(#"foo", [NSNumber numberWithInt:4], #"bar", nil);
I'm familiar with variable parameter length but not too sure how to store the args and then send them to std::cout. Is this even possible?
Notice! I want to send any kind of object which can handle the << operator. Just look at this function as a substitute for:
std::cout << "test" << someObject << int << someOtherObject;
I am using boost and would like to keep it platform independent. This function will be part of a logging class in a shared lib.
It doesn't work in C# too because the format string is missing anyway concept is clear. In C you can do something like this (as seen in dbgprint, if you have variadic macro feature)
#define printfex(...) printf(__VA_ARGS__)
If you're so lucky to use C++11 you can write this prototype:
template<class... T>
void printfex(const std::string& format, T... args);
You cannot use run-time variadic parameters in C++- that's a basic fact. You must use the same technique that the C++ streams do - operator overloading. Fortunately, C++ already contains such functionality.
void f(const std::stringstream& str) {
std::cout << str;
}
int main() {
int i = 5;
f(std::stringstream() << "i is equal to " << 5);
}
Sorry but I don't know very much about C#. Do you want to send a list of parameters to std::cout? That's not complicated:
void formatString (const std::vector<std::string>& args)
{
for (int i=0; i<args.size (); ++i)
{
std::cout << args[i];
}
std::cout << std::endl;
}
And you can store the elements in the following way:
std::vector test (2);
test[0] = "one";
test[1] = "two";
formatString (test);
UPDATE
Copy & Paste this into a .cpp file and compile it.
You have to implement the IPrintable interface for every class you want to log. Maybe is not the most efficient solution but it works.
#include <iostream>
#include <string>
#include <vector>
class IPrintable
{
public:
virtual ~IPrintable () { }
virtual std::string toString () const = 0;
};
class ClassA : public IPrintable
{
public:
std::string toString () const
{
std::string s = "Class A to string";
return s;
}
};
class ClassB : public IPrintable
{
public:
std::string toString () const
{
std::string s = "Class B to string";
return s;
}
};
void print (const std::vector<IPrintable*> args)
{
for (int i=0; i<args.size (); ++i)
{
std::cout << args[i]->toString () << std::endl;
}
}
int main (int argc, char* argv[])
{
ClassA a;
ClassB b;
std::vector<IPrintable*> v (2);
v[0] = &a;
v[1] = &b;
print (v);
return 0;
}