3

here is what I would like to do:

typedef std::function<void(const callback&)> callback;

(Ie: defining a std::function that can pass as first arg an object of same type as itself).

However this doesn't compile (callback is not know when parsing argument, even if compiler knows the size of the arg as it's a const ref)

Does anyone knows some kind of hack (perhaps with template?) less ugly than the one I'm using:

struct scallback;
typedef std::function<void(const scallback&)> callback;
struct scallback { callback value; };

It's "ugly" because I have to use arg.value and not arg directly..

NB: I have to use std::function and not C-Like pointer, preventing using void* and cast. Thanks

Bob

Bob
  • 43
  • 1
  • 5
  • Out of curiosity, what kind of callback takes itself as a parameter? – Cameron Nov 18 '14 at 19:23
  • if you got what you wanted, your first line would result in an endless recursive typedef... – Red Alert Nov 18 '14 at 19:23
  • If you're trying to forward declare a struct, `const struct scallback&` would be fine. However I don't see why you need it to be the same name. I smell an X and Y problem. –  Nov 18 '14 at 19:25
  • @Cameron : callback will not call itself, but will call another object of same type – Bob Nov 18 '14 at 19:33
  • @Read Alert: well it's possible to define a class A with a function member that take a const class& A (or a A*) as argument – Bob Nov 18 '14 at 19:35
  • Have you tried defining such a function without using a typedef? (Hint: you haven't.) – molbdnilo Nov 18 '14 at 19:44
  • @molbdnilo : that's why I need a typedef. NB: in pure C style, we could define function argument as void* and use C-Cast inside the function. I'm trying to do such a thing with std::function (but it's not possible to cast generic std::function to void* if you want to capture variables) – Bob Nov 18 '14 at 19:54
  • @Bob No, that's why you *can't* have a typedef. The type is "infinite". – molbdnilo Nov 18 '14 at 20:16
  • @molbdnilo It would have been infinite if the argument was passed by value, not by const ref or by pointer – Bob Nov 18 '14 at 20:28

2 Answers2

2

You are right. The type is not known at this point as it has not been defined yet. It's just in the middle of being defined.

What you can try is to inherit a new class from std::function<> instead of type-aliasing it. You will be able to reference the subclass name in the parent class template instantiation similarly to CRTP and thanks to C++11 you will be able to import all constructors in a simple line.

This seems to work:

#include <functional>

struct callback : std::function<void(const callback&)> {
  using std::function<void(const callback&)>::function;
};

void test(const callback& cb) {}

int main() {
    callback cb = test;
    test(cb);
    return 0;
}
Community
  • 1
  • 1
Krizz
  • 11,362
  • 1
  • 30
  • 43
  • can't test inheriting constructors as I'm with gcc 4.6.3 < 4.8 - but your solution seems the best :) – Bob Nov 18 '14 at 21:54
1

Here is what I have which seems a bit better:

struct callback_arg;
typedef std::function<void(const callback_arg&)> callback;

struct callback_arg : callback // callback_arg can be seen as a callback
{
    // callback can be seen as a callback_arg
    callback_arg(const callback& a) : callback(a) 
    {
    };
};

void Foo(const callback& val) {};
void Fuu(const callback& val) {};

int main()
{
    callback foo = Foo;
    callback fuu = Fuu;

    foo(fuu); // compiles correctly

    return 0;
}
Bob
  • 43
  • 1
  • 5