1

I'm having a class that contains a function pointer. I would like to initialize various instances of the class statically but I can't figure out the correct syntax for this.

Let's say, this is my class

    class fooClass
    {
        int         theToken;
        string      theOutput;
        bool        (*theDefault)( void );
    };

I now would like to create a static instance of this, like this…

    fooClass test
    {
        1,
        "Welcome",
        (){ return (theToken & 1 ) ? true : false; }
    };

As I said, I can't figure out the proper syntax for the function pointer line. Or is it even possible like this? I'd really like not having to break out every function I create this way into its own function declaration.

What I'm trying to do is, allow each instance to have a unique default function because each instance represents a unique data-driven building block of a bigger system. The code I put in there is just for illustrative purposes. This default function will access certain global variables as well as some of the member variables and if need be I could pass this into the function.

Could someone point me in the right direction how I'd have to write the initialization for it to work under C++14?

Striding Dragon
  • 225
  • 1
  • 9
  • 3
    So what you want is a [*lambda expression*](http://en.cppreference.com/w/cpp/language/lambda)? – Some programmer dude Mar 28 '18 at 05:49
  • Yes, I tried that, too, but can't seem to get the syntax right. [=]() { return (theToken & 1 ) ? true : false; } – Striding Dragon Mar 28 '18 at 05:54
  • 1
    It seems like what you *really* want is a normal standard *member function*. Like `bool theDefault() { return ... ; }`. You should probably get [a good book or two](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282#388282) and read. – Some programmer dude Mar 28 '18 at 05:56
  • You cannot do that with just a function pointer not taking arguments, as in your example you are referring to member values, and a function pointer doesn't receive any `this` pointer. If you didn't need to capture anything you could have used the lambda syntax (as such a lambda has a conversion to function pointer), but as you need to capture the instance (by reference!) there's nothing you can do with the struct declaration as is. You can succeed using `std::function`, but you should probably explain a bit better what are you trying to achieve here. – Matteo Italia Mar 28 '18 at 06:00
  • @some-programmer-dude No, I do not want a standard member function. Each instance will have an individual custom function… hence the function pointer. – Striding Dragon Mar 28 '18 at 06:04
  • Then you can not use lambdas. Only a non-capturing lambda can decay to a function pointer. And without an object instance you can't capture the member variables. Perhaps use [`std::function`](http://en.cppreference.com/w/cpp/utility/functional/function) and possibly [`std::bind`](http://en.cppreference.com/w/cpp/utility/functional/bind)? Or use a visitor pattern or some other design-pattern so you don't need the member function pointer at all? – Some programmer dude Mar 28 '18 at 06:07
  • @matteo-italia What I'm trying to do is, allow each instance to have a unique default function because each instance represents a unique data-driven building block of a bigger system. The code I put in there is just for illustrative purposes. This default function will access certain global variables as well as some of the member variables. – Striding Dragon Mar 28 '18 at 06:07
  • And please edit your question with the details about the problem you try to solve, the motivation behind your current solution. It's a rather crucial detail that should be inside the body of the question and not as a comment. – Some programmer dude Mar 28 '18 at 06:10
  • I could easily pass this into the function if that would help, and I don't see how std::function or std::bind would address my problem at all. I know that I could always break the function out and insert a pointer to it into the class instantiation, but I was hoping there is a more streamlined way to do this. – Striding Dragon Mar 28 '18 at 06:10

1 Answers1

3

If you want to refer to struct members inside the function, you cannot do with just a plain function pointer not receiving any argument, as it doesn't receive the this pointer.

My advice is to at very least change it to a pointer to a function taking the instance as an argument, then in initialization you can pass a capture-less lambda (which can be converted to a plain function pointer):

class fooClass
{
    int         theToken;
    string      theOutput;
    bool        (*theDefault)( fooClass *that);

    // you may provide a helper for ease of use
    bool Default() { return theDefault(this);} 
};

fooClass test
{
    1,
    "Welcome",
    [] (fooClass *that){ return (that->theToken & 1 ) ? true : false; }
};

You can also use an std::function<bool(fooClass*)> to allow even functors, lambdas with captures & co. if you are ok with the increased overhead.


You may be tempted to use a plain std::function<bool()> instead, and use a lambda capturing the instance by reference, such as

fooClass test
{
    1,
    "Welcome",
    [&test] (){ return (test->theToken & 1 ) ? true : false; }
};

This does work, but is extremely dangerous if test happens to be copied, as theDefault will still refer to test even in the copy (and even after the original will have been destroyed).

(incidentally, this is how OOP is often done in languages such as Lua, but there (1) objects are not copied and (2) automatic memory management makes sure that closures "keep alive" the objects they capture)

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299