My question is: how do I pass a class member function into for_each
Code I am trying to get to work: (works when function is defined outside of class)
The part which fails is commented out - the one using for_each with function as the class member function
Any advice on how to get this to work?
#include <iostream>
#include <algorithm>
#include <vector>
void my_function(std::string str)
{
std::cout << "processing settings: " << str << std::endl;
}
class Settings_vector{
public:
std::vector <std::string> settings;
Settings_vector(){ // push back vector of objects
settings.push_back("settings 1");
settings.push_back("settings 2");
settings.push_back("settings 3");
settings.push_back("settings 4");
}
void tester(std::string settings_string){
std::cout << "processing settings: " << settings_string << std::endl;
}
};
int main()
{
//std::vector<std::string> my_vector;
Settings_vector settings_vector;
std:: cout << "doing things the non-class way\n" << std::endl;
for_each(settings_vector.settings.begin(), settings_vector.settings.end(), my_function); // testing function
// WORKS
/*
std:: cout << "doing things the modern way\n" << std::endl;
for_each(settings_vector.settings.begin(), settings_vector.settings.end(), settings_vector.tester); // testing function
// FAILS
*/
std:: cout << "doing things the oldskool way\n" << std::endl;
for (int i = 0;i<settings_vector.settings.size();++i) {
settings_vector.tester(settings_vector.settings[i]);
}
// WORKS
return 0;
}
The easiest way would be to use a lambda expression. A bit more complex approach is to use std::bind() to bind all known arguments (here the instance of the class to the member function) and leave unknown arguments with placeholders _1, _2, etc.
#include <iostream>
#include <algorithm>
#include <vector>
class Settings_vector
{
Settings_vector()
: settings { "settings 1"
, "settings 2"
, "settings 3"
, "settings 4"
}
{}
void tester(std::string settings_string)
{ std::cout << "processing settings: " << settings_string << std::endl; }
public:
std::vector <std::string> settings;
};
int main()
{
Settings_vector settings_vector;
using namespace std;
using namespace std::placeholders; // for _1
// Possibility Nr. 1: Use a Lambda Function
for_each( settings_vector.settings.begin(), settings_vector.settings.end()
, [&settings_vector](auto input){ settings_vector.tester(input); }
)
;
// Possibility Nr. 2: Partially bind existing arguments and use placeholders for others
for_each( settings_vector.settings.begin(), settings_vector.settings.end()
, std::bind(&Settings_vector::tester, &settings_vector, _1);
)
;
return 0;
}
Explanations:
I think a lambda is straight forward. In the square brackets, you declare what goes into a closure. Here we pass settings_vector. Preceding it with & means that this instance is passed by reference. In the parenthesis, we declare the parameters to the function. I cheated a little bit, as auto in lambda expressions was introduced in C++14, but you can write it as type std::string as well.
std::bind() binds parameters to a function pointer and returns a callable object. If all parameters are present, the returned callable has no parameters and can be called like: callable(). Here, we want a callable to accept the result of the iteration. Thus, we use a placeholder _1, which states that this argument will be changed at call-time. Now 2 things remain:
Getting a pointer to a member function. This is done by using &TypeName::MemberName, in this case &Settings_vector::tester.
Passing a this pointer to a member function call: &settings_vector. When calling a member function, an object must be passed for which this member function is called. Because we just got a pointer to a member function without any bound object to it, that's why the second param is &settings_vector.
For a more concise sintax, use a static class method. I've slightly edited your code for improved readability within the context of your question (aka removing distractions).
#include <iostream>
#include <vector>
class Settings {
public:
std::vector <std::string> settings;
Settings(std::initializer_list<std::string> l)
: settings(l) {
}
static void tester(std::string const& str) {
std::cout << "processing settings: " << str << std::endl;
}
};
int main() {
Settings sv {"settings 1", "settings 2", "settings 3", "settings 4"};
for_each(sv.settings.begin(), sv.settings.end(), Settings::tester);
return 0;
}
Related
I'm using pybind11 to create python bindings for a C++ library whose source I cannot change. It contains a class that defines member functions with rvalue reference arguments (eg T &&val). I am unable to create a binding to a member function with rvalue reference arguments but binding to a non-member function with identical arguments works as expected.
A simplified example looks like this:
struct Foo {
// Cannot create a pybinding for this method.
void print_ref(int &&v) const {
std::cout << "Foo::print_ref(" << to_string(v) << ")" <<std::endl;
}
};
// Pybinding for standalone function works as expected.
void print_ref(int&& val) {
std::cout << "print_ref(" << to_string(val) << ")" << std::endl;
};
The pybind11 code looks like this:
PYBIND11_MODULE(refref, m) {
py::class_<Foo>(m, "Foo")
// Both of these attempts to create a pybinding FAILs with same error.
.def("print_ref", &Foo::print_ref)
.def("print_ref", (void (Foo::*) (int&&)) &Foo::print_ref);
// This pybinding of standalone function is SUCCESSful.
m.def("print_ref", &print_ref);
}
The compilation error on the first binding attempt is:
pybind11/bin/../include/site/python3.4/pybind11/pybind11.h:79:80: error: rvalue reference to type 'int' cannot bind to lvalue of type 'int'
initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(args...); },
^~~~
pybind11/bin/../include/site/python3.4/pybind11/pybind11.h:1085:22: note: in instantiation of function template specialization 'pybind11::cpp_function::cpp_function<void, Foo, int &&,
pybind11::name, pybind11::is_method, pybind11::sibling>' requested here
cpp_function cf(method_adaptor<type>(std::forward<Func>(f)), name(name_), is_method(*this),
^
refref.cpp:31:3: note: in instantiation of function template specialization 'pybind11::class_<Foo>::def<void (Foo::*)(int &&) const>' requested here
.def("print_ref", &Foo::print_ref);
Any ideas on what I may be doing wrong? Since it works fine with non-member functions, I'm inclined to suspect a pybind11 issue but thought I would check here first.
Indeed, the problem comes from rvalues. I learned quite a few things from this SO answer and this blog post.
There's a nice workaround : you can create a wrapper class that will redirect calls to the C++ library you cannot change, taking care of the rvalue with the std::move semantic.
#include <iostream>
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
namespace py = pybind11;
struct Foo {
void print_ref(int&& v) const {
std::cout << "Foo::print_ref(" << +v << ")" <<std::endl;
}
};
// This class will interface between PyBind and your library
class Foo_wrap{
private:
Foo _mimu;
public:
void print_ref(int v) const{
_mimu.print_ref(std::move(v));
}
};
PYBIND11_MODULE(example, m) {
py::class_<Foo_wrap>(m, "Foo_wrap")
.def(py::init())
.def("print_ref", &Foo_wrap::print_ref);
}
That you can call in Python with
import example as fo
wr = fo.Foo_wrap()
wr.print_ref(2)
I want to access a variable in multiple .cpp files. I looked into several resources. I could not solve it though. I am using cmake to build all the codes in this project. Following is an example that exactly matches with my problem. Basically, I want val to print 42 in both code1.cpp and code2.cpp. When, I build these three files it complains: undefined reference to 'he::val' collect2: error:ld returned 1 exit status for both the .cpp files.
header1.h
#ifndef HEADER1_H
#define HEADER1_H
#include <iostream>
namespace he {
extern int val;
}
#endif // HEADER1_H
code1.cpp
#include "header1.h"
#include <iostream>
using namespace he;
int func()
{
std::cout << val << std::endl;
}
int main()
{
val=20;
func();
return 0;
}
code2.cpp
#include <iostream>
#include "header1.h"
using namespace he;
int main()
{
std::cout << val << std::endl;
}
extern int val;
Is a variable declaration. You need, somewhere (in one of your cpp files), to define the variable:
int val;
Actually, since you have two main() functions, these are two separate programs. Then your variable definition needs to be in both, like this:
namespace he {
int val;
}
But your extern declaration in the header file makes your variable global, which is usually frowned upon. It all depends, of course on what your purpose is.
Also, since two main() functions mean two separate programs, there is no variable sharing.
Iam confused with the below question I did the program as per my understanding but it crashes what am I doing wrong? If someone can please assist me it would be much appreciated.
my main.cpp looks like this:
#include <iostream>
#include <iomanip>
#include "Number.h"
using namespace std;
int main()
{
Number n1(10);
Number n2 = n1;
n2.printNum();
n2.addOne();
n1 = n2;
n1.printNum();
return 0;
}
Then my header file looks like this:
#include <iostream>
using namespace std;
class Number
{
int *p;
public:
Number(int);
void addOne();
void printNum();
};
And the below parts for the constructor I need to complete there where it shows comments that's the part I should complete:
#include <iostream>
#include "Number.h"
using namespace std;
Number::Number(int a1)
{
*p = a1;//write the code needed to initialise the value of the member variable with a1
}
void Number::printNum()
{
cout << "The number is " << *p << endl;
}
void Number::addOne()
{
*p++;//write the code needed to increment the value of the member variable by one.
}
Then the question asks the below what should I do to the code to use the BIG THREE?
Consider the following program. Complete the class definition (where you are asked to) and check the output. You can see that that program works without error once it is completed. However, experts suggest that in any class that uses pointers and the new operator it is better to follow the rule of The Big Three. Modify the class definition to follow the rule of The Big Three and submit the new program and the output. Demonstrate the use of this pointer.
Thank you
Rohan
So here's my code I'm working with:
#include <iostream>
class Node
{
public:
void speak(){std::cout << "I'm a base node" << std::endl;}
};
class Child : public Node
{
public:
void speak(){std::cout << "I'm a child node" << std::endl;}
};
int main()
{
Node node;
Child child;
node.speak();
child.speak();
std::cout << "= Pointers..." << std::endl;
Node* pnode = &node;
Node* pchild = &child;
pnode->speak();
pchild->speak();
}
And here's the output:
I'm a base node
I'm a child node
= Pointers...
I'm a base node
I'm a base node
The pchild->speak(); calls the Node's method and not the Child's one.
Now my problem is that I may have many different types of nodes, with varying number of connections. Thus I cannot declare a member pointer with a ChildX class, but only with a generic Node class. But each node will have a certain method that I want called.
I've tried to have a pointer to that method itself instead of to the class (since it would always be int (*foo)() type), but the compiler complains about invalid use of non-static member function.
So both of my approaches don't work. Neither pointer to a class, nor pointer to classes member function.
Familiarize yourself with virtual functions and polymorphism - both key concepts in c++.
In your question you simply need to define
virtual void speak(){std::cout << "I'm a base/child node" << std::endl;}
I would like to overload the << operator for my class from a method display already defined. I get an compiler error of no match for operator <<.
Here is a minimal example:
#include <iostream>
using namespace std;
class MyClass
{
public:
MyClass()
{}
ostream& display(ostream& out) const
{
out << "Display message" << endl;
return out;
}
ostream& operator<< (ostream& out) const
{
ostream& output = display(out);
return output;
}
};
int main()
{
MyClass C1;
cout << C1 << endl;
return 0;
}
Although C1.display(cout); woks without problems!
You have defined operator<< as a member function of MyClass. Therefore, you must call it like member functions are called (object on the left, parameter on the right), like this:
C1 << cout;
But that doesn't seem to be what you want. You probably want to be able to call it like this:
cout << C1;
In that case the function can't be a member of MyClass. It would have to be a member of cout, or a free function (outside any class). And in this case it must be a free function because you can't change the definition of cout.
So, to declare operator<< as a free function, it needs to have two arguments (left-hand-side and right-hand-side):
ostream& operator<< (ostream& out, const MyClass& c) { ... }
Now you can call it with an ostream on the left and a MyClass object on the right, like this:
cout << C1;