Take the following minimal example:
using Type1 = std::function<void(void)>;
template <typename T>
using Type2 = std::function<void(T)>;
Type1 whyDoesThisWork;
Type2<void> andYetThisDoesNot;
If the second type alias, I get the error "Argument may not have 'void' type". (I tested with Xcode 4.5, Clang/c++11/libc++, OS X 10.7.)
I find this curious: I would have expected Type1
and Type2<void>
to behave identically. What's going on here? And is there a way to rewrite the second type alias so I can write Type2<void>
and get std::function<void(void)>
instead of an error?
Edit I should probably add that the reason I want this is to allow for something like the following:
template <typename ... T>
using Continuation = std::function<void(T...)>;
auto someFunc = []() -> void {
printf("I'm returning void!\n");
};
Continuation<decltype(someFunc())> c;
Continuation<decltype(someFunc())>
becomes Continuation<void>
and I get the error.
I don't have an actual answer, only what I said in the comment: You can't have void
as a function type, as in:
int foo(int, char, void, bool, void, void); // nonsense!
I believe that T(void)
is only allowed as a compatibility notation for C (which distinguishes declarations and prototypes, very differently from C++, and which needs to be able to say "no arguments").
So, the solution should be variadic:
template <typename ...Args> using myType = std::function<void(Args...)>;
That way you can properly have no arguments:
myType<> f = []() { std::cout << "Boo\n"; }