pointer to member function inside namespace - c++

I've got a namespace MyNamespace containing a class MyClass with many static public members functions.
What I need to do, is to build, inside the namespace, a map containing a pointer on every public members functions of the class
Here the code:
#include <iostream>
#include <map>
namespace MyNamespace {
class MyClass;
typedef bool (*fctPtr)(void);
typedef std::map<std::string, fctPtr> fctMap;
};
class MyNamespace::MyClass {
public:
static bool func1(void) { return true; };
static bool func2(void) { return true; };
static bool func3(void) { return true; };
static bool func4(void) { return true; };
};
MyNamespace::fctMap MyFctMap;
void execFct() {
MyNamespace::MyClass obj;
MyNamespace::fctPtr fctMemb;
fctMemb = MyFctMap["func1"];
(obj.*fctMemb)();
}
int main() {
MyFctMap["func1"] = &MyNamespace::MyClass::func1;
MyFctMap["func2"] = &MyNamespace::MyClass::func2;
MyFctMap["func3"] = &MyNamespace::MyClass::func3;
MyFctMap["func4"] = &MyNamespace::MyClass::func4;
execFct();
}
And what the compiler says:
% clang++ draft.cc
draft.cc:29:7: error: right hand operand to .* has non pointer-to-member type
'MyNamespace::fctPtr' (aka 'bool (*)()')
(obj.*fctMemb)();
^ ~~~~~~~
1 error generated.
I don't understand why I got this error neither what to do to resolve the problem. Idea?
Edit: I'm using c++98 and no boost.
Working with a typedef bool (MyClass::*fctPtr)(void) drives me to this kind od error, at map assignment time.
error: assigning to 'mapped_type' (aka 'bool (MyNamespace::MyClass::*)()') from
incompatible type 'bool (*)()'
MyFctMap["func1"] = &MyNamespace::MyClass::func1;
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Since the functions you are referencing are static, you don't need the obj class reference. Simply call fctMemb();. You might also consider if you need these functions mapped in such a way, oftentimes you don't need that dynamic aspect to function references in C++ and instead should be using templates.

A pointer to a function is not the same as a pointer to a member function. The important thing to remember is that all (non-static) member function actually have a hidden first argument which is what becomes the this pointer. Therefore a function pointer and a member function pointer can't ever be compatible.
However, you should look into std::function and std::bind:
namespace NyNamespace
{
typedef std::function<bool()> fctPtr;
...
}
MyNamespace::MyClass myObject;
MyFctMap["func1"] = std::bind(&MyNamespace::MyClass::func1, myObject);

The idea is fctMemb(); :-)
fctPtr, as the compiler says, is not a pointer to member type...

Static member functions are not like normal member functions. They have access to class private and protected members, but they are not tied to object instances and thus can't access this pointer nor any non-static members.
Their type is that of normal function pointers and they can't be bound to member function pointers (and normal function pointers is what you have in your code).
You call them like normal functions:
fctMemb();
Btw, the sytax to form member function pointers is different:
struct Foo {
void f() {}
};
void (Foo::* mem_fun_ptr)() = &Foo::f;

Related

How to make increment/decrement static variable for an API?

#include <iostream>
class Test {
public:
static int numelem;
Test() {}
~Test() {}
int increment();
};
int Test::numelem = 0;
int Test::increment()
{
return ++Test::numelem;
}
So I want to make a counter for my Stacks data structure.
Whenever I push, it increments and when popped it decrements.
My code works, but int Test::numelem = 0; is a global variable.
I tried using inline but unfortunately I have C++14.
I only put the static int numelem instead of the whole Stack class to focus on one feature.
Is there an alternative way I can put int Test::numelem = 0; inside the class without getting any error?
This is the typical workaround. It's particularly useful for templates.
class Test {
public:
static int& numelem() {
static int val = 0; // or your initializer here
return val;
}
int increment() {
return ++numelem();
}
};
Of course, now you're accessing it with the syntax Test::numelem() instead of just Test::numelem. But something like ++Test::numelem() still works just fine.
but int Test::numelem = 0; is a global variable.
Technically, it is not a global variable but a class static member. Functionally they behave very similarly.
Is there an alternative way I can put int Test::numelem = 0; inside the class without getting any error? unfortunately I have C++14.
With C++14 the out-of-class definition for a nonconst static data member should be in the same namespace scope where the class was defined(global namespace in your example). So there is no way of defining a nonconst static data member inside the class in c++14 as we can't use inline in c++14 and the only way of defining a nonconst static data member is to put a definition at namespace scope.
This can be seen from class.static.data:
The declaration of a static data member in its class definition is not a definition and may be of an incomplete type other than cv-qualified void. The definition for a static data member shall appear in a namespace scope enclosing the member's class definition.
But with C++17 we can use inline to define a non-const static data member inside the class.

Initializing a class' function pointer member to the same class' function member

In the header file of class Class1, I've declared a function pointer fn_ptr and a function called myfunc(int,int):
class Class1
{
private:
bool (*fn_ptr)(int,int);
public:
Class1(); //Default Constructor
bool myfunc(int,int);
};
I want to have fn_ptr point to Class1's myfunction defined like so in the class's library file:
Class1::Class1()
{
fn_ptr = myfunc; //Initialization in the
}
Class1::myfunc(int a, int b)
{
return a<b;
}
Compiling resulted in an error:
error: argument of type 'bool (Class1::)(int,int)' does not match 'bool (*)(int,int)'
As user4581301 wrote in the comment, once you have a (non-static) member function, it takes a "hidden" pointer to the class's object, so you can't do directly what you tried here - the interfaces just don't match.
Also, there are currently more convenient facilities for function indirection that bare pointers.
Suppose you do the following. First, declare the class like this:
#include <functional>
using namespace std;
class Class1
{
private:
std::function<bool(int, int)> fn;
public:
Class1(); //Default Constructor
bool myfunc(int,int){ return true; }
};
Note how the member fn is of type std::function, which is more convenient and versatile.
Now in the constructor, you can simply initialize it with a lambda function:
Class1::Class1() :
fn([this](int i, int j){return myfunc(i, j);})
{
}
It says that for any i and j, just call myfunc (on this objet) on these arguments, and return the result.
Full code
Make sure to build using c++11 settings.
#include <functional>
using namespace std;
class Class1
{
private:
std::function<bool(int, int)> fn;
public:
Class1(); //Default Constructor
bool myfunc(int,int){ return true; }
};
Class1::Class1() :
fn([this](int i, int j){return myfunc(i, j);})
{
}
int main()
{
Class1 c;
}
In addition to #Ami's excellent answer about using std::function instead, member function pointers have different syntax, which is why it didn't work for you.
bool (Class1::*fn_ptr)(int,int); //note the Class1::
fn_ptr = &Class1::my_func; //the &Class1:: is necessary, forgetting it is a compilation error
Calling it is different, too. It needs an instance of the class to be called on.
Class1 c;
(c.*fn_ptr)(1, 2); //or (this->*fn_ptr) too

Is it possible to define an anonymous member function in C++

I have a fun use case for my little pet project where I would like to have a
static map<std::string, pointer-to-member-function>
in a class. This is easy, if a bit cumbersome syntax, and it works beautifully.
What I would like to do also is to have the pointer-to-member-function be a simple lambda-expression in my static initializer. This would make it sooo easy to package things like this in a nice macro.
I want the pointer-to-member-function to have access to private class members, hence I cannot really use a normal lambda with "this" as a parameter.
However I cannot seem to find any way to define an anonymous member function -- c++ lambdas all seem to be free global functions?
If you have std::function<void(const MyClass&)> in your map then you can store a lambda that takes an instance of your class as a parameter. As long as the lambda is defined in a member function of MyClass it will be able to access private class members of MyClass:
#include <map>
#include <functional>
class MyClass {
private:
void myPrivate() const { }
public:
static std::map<std::string, std::function<void(const MyClass&)>> funcs;
static void initFuncs() {
funcs["test"] = [](const MyClass& mc) { mc.myPrivate(); };
}
};
std::map<std::string, std::function<void(const MyClass&)>> MyClass::funcs;
int main() {
MyClass::initFuncs();
MyClass mc;
MyClass::funcs["test"](mc);
}
Live demo.

Calling a free floating function within a class

I have a method inside the Foo class that needs to call the free floating function freeFloat. However, calling it results in a out of scope error.
Foo.cpp: In member function ‘virtual bool Foo::method()’:
Foo.cpp:351:24: error: ‘freeFloat’ was not declared in this scope
freeFloat();
The structure of the code looks something like this:
class Foo {
public:
virtual void method() {
freeFloat();
}
};
int main(){
}
bool freeFloat(){
}
Can this be done? If so, is it considered poor practice or in most cases OK? Is there a better placement for each method?
The function shall be declared before the class definition if it refers to the function.
Any name in C++ shall be declared before its using.
You need to declare the function before calling it....
bool freeFloat();
class Foo {
public:
virtual void method() {
freeFloat();
}
};
int main(){
}
bool freeFloat(){
}
You need to declare freeFloat before you can call it. Either move the function definition to the top or add:
bool freeFloat();
to the top.

typedef function pointer that takes argument ClassName* before defining ClassName?

I have the following situation:
typedef void (*F_POINTER)(ClassName*);
class ClassName {
public:
F_POINTER f;
}
This happens because an instance of ClassName needs to pass a pointer itself to the client. However, If I write things in this order, I get complains about ClassName not declared, whatnot. However, if I switch them around, I get complains about F_POINTER not being declared when I declare the instance in the class.
So maybe I'm missing something simple here, but how would I accomplish this?
Forward declaration:
class ClassName;
typedef (*F_POINTER)(ClassName*);
class ClassName {
public:
F_POINTER f;
}
Or shorter:
typedef (*F_POINTER)(class ClassName*); // implicit declaration;
This seems to be working under GCC 4.5.2 (mingw32):
typedef void (*F_POINTER)(class ClassName);
class ClassName {};
void f (ClassName) {}
int main ()
{
F_POINTER x = f;
}
I wouldn't trust my life on whether it is legal C++ or not, not even the pointer version described by other people. Forward declarations and pointers do not solve everything, for example it is not possible to declare methods that throw pointers of incomplete types, you need full definition for that. This might be similarly illegal, just accepted by compilers.
Forward declare ClassName. The type can be incomplete to use a pointer to it.
class ClassName;
typedef (*F_POINTER)(ClassName*);
class ClassName { ... };
Alternatively, move the typedef inside the class. Also consider using boost::function/std::function instead of function pointers.
Either you can forward declare it as,
class ClassName;
typedef void (*F_POINTER)(ClassName*); // assume that return is `void`
before the F_POINTER or you can use the template trick to avoid such hassels for every class:
template<typename RETURN, typename ARGUMENT>
struct FuncPtr { typedef RETURN (*F_POINTER)(ARGUMENT); };
Usage:
class ClassName {
public:
FuncPtr<void,ClassName*>::F_POINTER f;
};