how can i build a typedef with variadic operator?
what i mean is that i need build these:

typedef std::function<void(void)> Event;//works fine, but for any parameters



typedef std::function<void(...)> Event; //no errors



Event test(int x, int y)=[](int x, int y)
        {
            int a=x+y;
            string b=tostring(a);
            MessageBox(NULL,b.c_str(),"hello",MB_OK);
        };

in these sample i get 1 error:

"invalid pure specifier (only '= 0' is allowed) before ']' token"
how can i fix the error?

Recommended Answers

All 10 Replies

You have to use a template alias. As so:

template <typename... Args>
using Event = std::function<void(Args...)>;

Event<int,int> test = [](int x, int y)
{
  int a=x+y;
  std::string b = std::to_string(a);
  MessageBox(NULL, b.c_str(), "hello", MB_OK);
};

The reason why your initial typedef worked is because it uses void(...) which represents a variadic function, not a variadic template. That makes it a valid declaration (I think), but a rather useless one, as you would technically have to assign to it a variadic function, not "any function", and I'm not sure you can do that with lambdas. And if I try with a more correct syntax to initialize Event test, there is still an error related to Event having an incomplete type, which indicates that having a std::function with a variadic function is not proper (which I can understand). Variadic functions are essentially obsolete and completely avoidable in C++11, so, stay away from that archaic feature.

You could also simply do this:

auto test = [](int x, int y) {
  int a = x+y;
  std::string b = std::to_string(a);
  MessageBox(NULL,b.c_str(),"hello",MB_OK);
};
commented: thanks +0

thanks for that my friend.
let me ask 1 thing: why i can't change the 'auto' keyword with typedef?

typedef auto Event;

error message:
"typedef declared 'auto'"
if the 'auto' is like a type, why i can't chnage the name?

and i get these error with your sample:
"non-static data member declared 'auto'"

seems that my best thing still be the pre-compiler way:

#define event(eventname, ... ) std::function<void(__VA_ARGS__ )> eventname

sample:

event(Move, (int x, int y)) = [](int x, int y) {;};
event(Visible) = []() {;};

but like we know the #define use it like a functions... but i wanted something like these:

event Move(int x, int y) = [](int x, int y) {;};
event Visible = []() {;};

No, you can't do that. auto is a reserved keyword that tells the compiler to infer the type from the expression that initializes the variable. In other words, it's a placeholder for a deduced type, it is not a type by itself.

ok.. but why that error message?
seems that i can't use lambdas with auto

ok.. but why that error message?

Because you cannot use auto for non-static data members. That's what the standard says, and that's what your compiler says, and so, that's as good as a fact of life that you have to accept. The rationale behind that rule is too much to explain. The auto keyword does not provide anything more than the convenience of not having to explicitly write out the type, and therefore, it's not necessary for anything, simply convenient where it is allowed to be used, but for non-static data members, it is not allowed, so you have to explicitly write the type instead (which you can always do).

seems that i can't use lambdas with auto

You certainly can use auto with lambdas. In fact, part of the rationale for introducing auto was to make the use of lambdas more convenient.

seems that my best thing still be the pre-compiler way:

Arrgh... What is it with you and archaic features and pre-processor tricks? It seems like you always come back to some MACRO to create odd constructs that I wouldn't even advise to do even outside of a MACRO, let alone in one. I tell you to stay away from MACROs, you run towards them. I tell you to stay away from variadic functions, you present a variadic function solution, and you double down with var-args macro in the mix... please stop hurting me like that.

but i wanted something like these:

event Move(int x, int y) = [](int x, int y) {;};
event Visible = []() {;};

What's the difference between that and the solution I gave you:

Event<int,int> Move = [](int x, int y) {;};
Event<> Visible = []() {;};

There is no difference, it's all the same amount of information and nearly identical syntax. What more do you want exactly? Is it just that you don't like C++ syntax and you want the code to just look like it's some other language? If so, there are some hard limits to how far you can go down that route, and you'll have to make compromises and be reasonable.

sorry let me ask 1 thing:
if i can do these(on construtor):

classname(std::function<void(...)> func)

why i can't do these?

std::function<void(...)> Event; //like you see is like creating a variable

The standard does not require a specialization of the std::function for variable argument functions. There are two reasons for that. First, variable argument functions (or C-style variadic functions) are not recommended to be used, ever, because they are completely unsafe from a type-checking point of view and have only been kept around in C++ for backward compatibility with C (e.g., variadic functions were used to implement standard C functions like printf()). Second, variable argument functions present some difficulties when it comes to implementing type-erasure, which is the technique used in implementing std::function such that it can store whatever is given to it (function pointer, lambda, etc.) and call it with perfect forwarding of the arguments it is called with.

Now, the reason why you can form something like std::function<void(...)> is that this invokes a specialization of std::function that does not exist, and therefore, it becomes what is called an "incomplete type". An incomplete type simply means that the compiler knows that you are invoking a type, but doesn't really know what that type is (e.g., it doesn't exist or hasn't been defined yet). There are certain things you can do with incomplete types, and others that you cannot do with them. Basically, anything that requires any knowledge about the type cannot be done with an incomplete type, such as declaring a variable of that type, calling a member function of it, and things like that. Some things don't actually require any knowledge about the type and can therefore be done with incomplete types, such as declaring a pointer or reference to that type, making typedefs or type aliases for it, and declaring variables or parameters of that type inside function templates (or member functions of class templates). This is why certain things work and others don't. But in this case, since the specialization of std::function that contains a variable argument function does not exist, there is no way to ever use it in a meaningful way, it doesn't exist! And it never will!

commented: thanks for all +3

thanks for all

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.