mem_fun_ref question - c++

Why is this code resulting in a compiler error?
#include <iostream>
#include <algorithm>
using namespace std;
class X
{
public:
void Print(int x)
{
cout << x << endl;
}
};
int main()
{
X x;
mem_fun_ref<void, X, int>(&X::Print) p;
};
Error
main.cpp:18: error: expected ; before p

mem_fun_ref is a function template, so it does not name a type.
mem_fun_ref<void, X, int>(&X::Print) is a function call that returns a value, so it makes no sense that there is a p following it.
The return value of that function call is a mem_fun1_ref_t<void, X, int>, in case you were looking for that.

Did you intend to write
mem_fun1_ref_t<void, X, int> p(&X::Print);
^^^^ ^^^
instead? mem_fun_ref is not a class template, but a function template.

Related

C++ how to pass an STL list to a function

I wrote the following code in C++. The declaration of the function "change_list" gives an error:
"incomplete type is not allowed"
and "identifier "list" is undefined". Do you know why?
I just followed the answers in this post: C++ pass list as a parameter to a function
#include <iostream>
#include <list>
typedef struct Point {
int x;
int y;
} Point;
Point* initPoint(int x, int y) {
Point* pt = (Point*)malloc(sizeof(Point));
pt->x = x;
pt->y = y;
return pt;
}
void change_list(list<Point*> &mylist){ // ERROR!!!
mylist.push_back(4);
}
int main()
{
using namespace std;
list<Point*> c1; // initiating a list
c1.push_back(initPoint(1, 1));
c1.push_back(initPoint(2, 2));
c1.push_back(initPoint(3, 3));
change_list(c1);
for (Point* c : c1)
cout << " " << c->x;
cout << "\n";
return 0;
}
The problem is statement mylist.push_back(4), in which you pass an integer whereas mylist expects a Point*. If you call it like mylist.push_back(new Point()) it compiles. BTW: maybe you should write std::list or place a using std::list somewhere after #include<list>.
There are two issues in your code :
You have used namespace std in main, either use std globally (bad practice) or use std::list.
In function change_list, push a valid Point type pointer, you are pushing an integer.
void change_list(std::list<Point*> &mylist){ // ERROR!!!
mylist.push_back(initPoint(8, 8));
}

Variables does not have class type, even though it is defined

I am trying to write a class which defines a std::map. The comparator of the map must be a function pointer. The function pointer can be passed to the class as an argument in class's constructor.
Below is the code I wrote:
#include <iostream>
#include <map>
#include <string>
#include <functional>
typedef std::function<bool(std::string x, std::string y)> StrComparatorFn;
bool FnComparator(std::string x, std::string y) {
return strtoul(x.c_str(), NULL, 0) < strtoul(y.c_str(), NULL, 0);
}
class MyClass {
public:
MyClass(StrComparatorFn fptr):fn_ptr(fptr){};
void Insert() {
my_map.insert(std::pair<std::string, std::string>("1", "one"));
my_map.insert(std::pair<std::string, std::string>("2", "two"));
my_map.insert(std::pair<std::string, std::string>("10", "ten"));
}
void Display() {
for (auto& it : my_map) {
std::cout << it.first.c_str() << "\t => " << it.second.c_str() << "\n";
}
}
private:
StrComparatorFn fn_ptr;
std::map<std::string, std::string, StrComparatorFn> my_map(StrComparatorFn(fn_ptr));
};
int main() {
MyClass c1(&FnComparator);
c1.Insert();
c1.Display();
}
I am getting a compile error in Insert:
error: '((MyClass*)this)->MyClass::my_map' does not have class type
my_map.insert(std::pair<std::string, std::string>("1", "one"));
Any solution to this issue?
That line
std::map<std::string, std::string, StrComparatorFn> my_map(StrComparatorFn(fn_ptr));
has a problem known as the most vexing parse. Basically, everything that can be interpreted as a function, will be:
Foo f(); //f is a function! Not a variable
In your case, my_map is parsed as a declared function without a definition. Using curly braces instead of curved braces will solve the problem, as list initialization can never be interpreted as a function:
std::map<std::string, std::string, StrComparatorFn> my_map{ StrComparatorFn(fn_ptr) };

Using binder1st with custom functor

I'd like to bind the first argument of my print functor to 0:
#include<iostream>
#include<functional>
using namespace std;
class Print : public std::binary_function<int,int,void>{
public:
void operator()(int val1, int val2)
{
cout << val1 + val2 << endl;
}
};
int main()
{
Print print;
binder1st(print,0) f; //this is line 16
f(3); //should print 3
}
The program above (based on an example from C++ Primer Plus) does not compile:
line16 : error : missing template arguments before ‘(’ token
What is wrong?
I don't want to use C++11 nor boost features.
Edited: operator() return type has been changed from bool to void for simplicity
As the error message says, you are missing template arguments before the (
This is what you want
std::binder1st<Print> f(print, 0);
However, you also need to make your operator() const as follows
bool operator()(int val1, int val2) const
Finally, this function needs to return something.
binder1st needs template-arguments, try
binder1st<Print> f(print, 0);
See the reference here.
Example
#include <iostream>
#include <functional>
#include <algorithm>
using namespace std;
int main () {
binder1st < equal_to<int> > equal_to_10 (equal_to<int>(),10);
int numbers[] = {10,20,30,40,50,10};
int cx;
cx = count_if (numbers,numbers+6,equal_to_10);
cout << "There are " << cx << " elements equal to 10.\n";
return 0;
}
std::binder1st is a class template, so it needs a template parameter.
binder1st<Print> f(print,0);
// ^^^^^^^
But if you really want to bind the second argument, then you need to use the aptly named std::binder2nd.

C++ Creating function map using templates and inheritance

I am trying to create a generic function map using templates.The idea is to inherit from this generic templated class with a specific function pointer type. I can register a function in the global workspace, but I'd rather collect all the functions together in the derived class and register these in the constructor. I think I am almost here but I get a compile error. Here is a stripped down version of my code:
#include <iostream>
#include <string>
#include <map>
#include <cassert>
using namespace std;
int f(int x) { return 2 * x; }
int g(int x) { return -3 * x; }
typedef int (*F)(int);
// function factory
template <typename T>
class FunctionMap {
public:
void registerFunction(string name, T fp) {
FunMap[name] = fp;
}
T getFunction(string name) {
assert(FunMap.find(name) != FunMap.end());
return FunMap[name];
}
private:
map<string, T> FunMap;
};
// specific to integer functions
class IntFunctionMap : public FunctionMap<F> {
public:
int f2(int x) { return 2 * x; }
int g2(int x) { return -3 * x; }
IntFunctionMap() {
registerFunction("f", f); // This works
registerFunction("f2", f2); // This does not
}
};
int main()
{
FunctionMap<F> fmap; // using the base template class directly works
fmap.registerFunction("f", f);
F fun = fmap.getFunction("f");
cout << fun(10) << endl;
return 0;
}
The error I get is:
templatefunctions.cpp: In constructor ‘IntFunctionMap::IntFunctionMap()’:
templatefunctions.cpp:33: error: no matching function for call to ‘IntFunctionMap::registerFunction(const char [3], <unresolved overloaded function type>)’
templatefunctions.cpp:15: note: candidates are: void FunctionMap<T>::registerFunction(std::string, T) [with T = int (*)(int)]
Juan's answer is correct: member functions have an implicit first parameter, which is a pointer to the type of which they are a member. The reason your code fails to compile is that your map supports function pointers with type int (*)(int), but the type of f2 is int (IntFunctionMap::*)(int).
In the specific case that you show here, you can use std::function, which implements types erasure, to present free functions and member functions as the same type. Then you could do what you are trying to do. Note: this requires C++11.
#include <iostream>
#include <string>
#include <map>
#include <cassert>
#include <function>
#include <bind>
using namespace std;
int f(int x) { return 2 * x; }
int g(int x) { return -3 * x; }
typedef std::function<int (int)> F;
// function factory
template <typename T>
class FunctionMap {
public:
void registerFunction(string name, T fp) {
FunMap[name] = fp;
}
T getFunction(string name) {
assert(FunMap.find(name) != FunMap.end());
return FunMap[name];
}
private:
map<string, T> FunMap;
};
// specific to integer functions
class IntFunctionMap : public FunctionMap<F> {
public:
int f2(int x) { return 2 * x; }
int g2(int x) { return -3 * x; }
IntFunctionMap() {
registerFunction("f", f); // This works
registerFunction("f2", std::bind(&f2, this, _1)); // This should work, too!
}
};
int main()
{
FunctionMap<F> fmap; // using the base template class directly works
fmap.registerFunction("f", f);
F fun = fmap.getFunction("f");
cout << fun(10) << endl;
return 0;
}

C++ : unresolved overloaded function when using function pointers

#include <iostream>
using namespace std;
class B
{
public:
int getMsg(int i)
{
return i + 1;
}
};
class A
{
B b;
public:
void run()
{
taunt(b.getMsg);
}
void taunt(int (*msg)(int))
{
cout << (*msg)(1) << endl;
}
};
int main()
{
A a;
a.run();
}
The above code has a class B inside a class A, and class A has a method taunt that takes a function as an argument. class B's getMsg is passed into taunt...The above code generated the following error message: "error: no matching function for call to 'A::taunt()'"
What's causing the error message in the above code? Am I missing something?
Update:
#include <iostream>
using namespace std;
class B
{
public:
int getMsg(int i)
{
return i + 1;
}
};
class A
{
B b;
public:
void run()
{
taunt(b.getMsg);
}
void taunt(int (B::*msg)(int))
{
cout << (*msg)(1) << endl;
}
};
int main()
{
A a;
a.run();
}
t.cpp: In member function 'void A::run()':
Line 19: error: no matching function for call to 'A::taunt()'
compilation terminated due to -Wfatal-errors.
I'm still getting the same error after changing (*msg)(int) to (B::*msg)(int)
b.getMsg is not the correct way to form a pointer to member, you need &B::getMsg.
(*msg)(1) is not the correct way to call a function through a pointer to member you need to specify an object to call the function on, e.g. (using a temporary) (B().*msg)(1).
The right way to do such things in OOP is to use interfaces so all you need to do is to define an interface and implement it in B class after that pass the pointer of instance which implements this interface to your method in class A.
class IB{
public:
virtual void doSomething()=0;
};
class B: public IB{
public:
virtual void doSomething(){...}
};
class A{
public:
void doSomethingWithB(IB* b){b->doSomething();}
};
This works in VS 2010. The output is the same on all lines:
#include <iostream>
#include <memory>
#include <functional>
using namespace std;
using namespace std::placeholders;
class A
{
public:
int foo(int a, float b)
{
return int(a*b);
}
};
int main(int argc, char* argv[])
{
A temp;
int x = 5;
float y = 3.5;
auto a = std::mem_fn(&A::foo);
cout << a(&temp, x, y) << endl;
auto b = std::bind(a, &temp, x, y);
cout << b() << endl;
auto c = std::bind(std::mem_fn(&A::foo), &temp, _1, y);
cout << c(5) << endl;
}
Basically, you use std::mem_fn to get your callable object for the member function, and then std::bind if you want to bind additional parameters, including the object pointer itself. I'm pretty sure there's a way to use std::ref to encapsulate a reference to the object too if you'd prefer that. I also included the _1 forwarding marker just for another way to specify some parameters in the bind, but not others. You could even specify everything BUT the class instance if you wanted the same parameters to everything but have it work on different objects. Up to you.
If you'd rather use boost::bind it recognizes member functions and you can just put it all on one line a bit to be a bit shorter: auto e = boost::bind(&A::foo, &temp, x, y) but obviously it's not much more to use completely std C++11 calls either.