Using 'void' template arguments in C++ - c++

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.

The short answer is "templates are not string substitution". void f(void) has meaning only so far as it is an alias for void f() in C++, in order to be backwards compatible with C.
The first step is to use variadics, as noted elsewhere.
The second step is figuring out how to map void returning functions to ... well, maybe something like std::function<void()>, or maybe something else. I say maybe something else because unlike the other cases, you cannot call std::function<void()> foo; foo( []()->void {} ); -- it isn't a true continuation.
Something like this maybe:
template<typename T>
struct Continuation
{
typedef std::function<void(T)> type;
};
template<>
struct Continuation<void>
{
typedef std::function<void()> type;
};
then use it like this:
auto someFunc = []()->void {};
Continuation<decltype(someFunc())>::type c;
which gives you the type you want. You could even add in an apply to continuation:
template<typename T>
struct Continuation
{
typedef std::function<void(T)> type;
template<typename func, typename... Args>
static void Apply( type const& cont, func&& f, Args... args)
{
cont( f(args...) );
}
};
template<>
struct Continuation<void>
{
typedef std::function<void()> type;
template<typename func, typename... Args>
static void Apply( type const& cont, func&& f, Args... args)
{
f(args...);
cont();
}
};
which lets you apply a continuation to an execution of a function uniformly if the incoming type is a void or if it is a non-void type.
However, I would ask "why would you want to do this"?

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"; }

Several answers already explain the rationale. To add to those answers, the specification says (C++11 §8.3.5[dcl.func]/4):
A parameter list consisting of a single unnamed parameter of non-dependent type void is
equivalent to an empty parameter list. Except for this special case, a parameter shall not have type cv void.
In your Type2 example, the T in void(T) is a dependent type--it depends on a template parameter.

When a function is declared to take a parameter of type void, as in std::function<void(void)>, that is really just a goofy way of saying that it takes zero parameters. But the way you've declared Type2 is as a std::function with a signature that returns nothing (void), but that takes 1 parameter. void is not a type that can be used as a parameter, it is just a way of declaring that there are no parameters. So it doesn't work with Type2, because that requires an actual type that can be used as a parameter.

Void can be interpreted as an empty parameter if you pass it to a function. You're not using a void pointer after all so
void func (void)
becomes
void func ()

Related

Type deduction for a member function pointer

I know there are similar questions on SO, but the usages there seem different to what I have. Here is my MRE:
#include <iostream>
#include <functional>
using namespace std;
void freeFunction() {}
struct Foo { void memberFunction() {} };
template<typename FunctionPtrT>
void foo(FunctionPtrT* f) { f(); }
template<typename InstanceT, typename FunctionPtrT>
void bar(InstanceT&& i, FunctionPtrT f) { std::mem_fn(f)(i); }
template<typename InstanceT, typename FunctionPtrT>
void baz(InstanceT&& i, FunctionPtrT* f) {}
int main() {
foo(&freeFunction); //Ok, obviously
bar(Foo(), &Foo::memberFunction); //Ok, how?!
// Error: candidate template ignored: could not match 'FunctionPtrT *' against 'void (Foo::*)()'
baz(Foo(), &Foo::memberFunction); //why?!
return 0;
}
Why is &Foo::memberFunction not resolving to a pointer? What is the type of f in bar? If it's not a pointer how am I able to pass it to std::mem_fun that is defined as template< class M, class T > /*unspecified*/ mem_fn(M T::* pm) noexcept;?
General suggestion for type investigations
I think the easiest way to answer questions like "what is the type of x in this context" is to put a static_assert(std::is_same_v<void, delctype(x)>); in that same context. The compiler will then tell you the static_assertion failed because void is not equal to the type of x, revealing what that type is.
is &Foo::memberFunction a pointer?
And there are variations of that.
For instance, if you truly want to know wheter &Foo::memberFunction is a pointer, then ask it this way:
static_assert(std::is_pointer_v<decltype(&Foo::memberFunction)>);
and the compiler will tell you something along the lines of
Static_assert failed due to requirement 'std::is_pointer_v<void (Foo::*)()>' [static_assert_requirement_failed]
so it just can't match against FunctionPtrT*.
As regards
What is the type of f in bar?
if you put
static_assert(std::is_same_v<void, decltype(f)>);
inside of bar, the compiler will tell you
Static_assert failed due to requirement 'std::is_same_v<void, void (Foo::*)()>'
meaning that the type of f is void(Foo::*)().
How does &Foo::memberFunction's type from a free function pointer?
Compare this with the error you get if you define
void f();
and assert
static_assert(std::is_same_v<void, decltype(f)>);
The compiiler will tell you
Static_assert failed due to requirement 'std::is_same_v<void, void (*)()>'
So the point is that void(*)(), a pointer to a free function from void to void, is different from void (Foo::*)(), a pointer member of Foo function from void to void.
How can I restrict a template to be instatiated only for member functions?
If you want your template to match only member functions, can go for
template<typename InstanceT, typename R, typename C>
void baz(InstanceT&& i, R C::* f) { }
or, if you want it to match any member function of Foo, you can clearly either change the order of the template parameters such that you can provide C manually
template<typename C, typename R, typename InstanceT>
void baz(InstanceT&& i, R C::* f) { }
which allows you to call baz<Foo>(/* args */);, or you can simply hardcode Foo in place of C:
template<typename R, typename InstanceT>
void baz(InstanceT&& i, R Foo::* f) { }
And what if I want to restrict the match to member function with a specific signature?
As you see, we already have a placeholder R, for the return type.
If we also wanted to have a placeholder for the arguments, we could go for this:
template<typename R, typename C, typename ...Args>
void baz(R (C::*f)(Args...));
Which will just match the same function as the previous example. I showed this just to make you see that, if you want to type the arguments out, you must put parenthesis around C::*f, or just C::*, if you want to omit the name (the lack of parenthesis is the typo in the comment under your question). Therefore, if you want to restrict the match to a specific signature, let's say void(), this is how you do it:
template<typename C>
void baz(void (C::*f)());
What is the type of f in bar?
The type of f in bar is void (Foo::*)() i.e., a pointer to a member function of class Foo that has no parameter and has the return type of void.
The reason baz(Foo(), &Foo::memberFunction); fails is that &Foo::memberFunction is a pointer to a member function is distinct from an ordinary pointer to some type.
In fact, member function pointers are not actually pointers. So the argument of type void (Foo::*)() cannot be passed to parameter FunctionPtrT* f.

Compile time deduction of template member function

Is it possible to get the return type of a template member function at compile time?
I guess I need something along the lines of:
template<class T>
struct SomeClass
{
// T must have a function foo(int), but do not know the
// return type, it could be anything
using RType = ??? T::foo(int) ???; // Is it possible to deduce it here?
}
What you want to do can be achieved by using the decltype operator together with the std::declval template.
decltype(EXPRESSION) yields – at compile time – the type that EXPRESSION would have. The EXPRESSION itself is never evaluated. This is much like sizeof(EXPRESSION) returns the size of whatever EXPRESSION evaluates to without ever actually evaluating it.
There is only one problem: Your foo is a non-static member function so writing decltype(T::foo(1)) is an error. We somehow need to obtain an instance of T. Even if we know nothing about its constructor, we can use std::declval to obtain a reference to an instance of it. This is a purely compile-time thing. std::declval is actually never defined (only declared) so don't attempt to evaluate it at run-time.
Here is how it would look together.
#include <type_traits>
template <typename SomeT>
struct Something
{
using RetT = decltype(std::declval<SomeT>().foo(1));
};
To see that it actually works, consider this example.
struct Bar
{
float
foo(int);
};
struct Baz
{
void
foo(int);
};
int
main()
{
static_assert(std::is_same<float, Something<Bar>::RetT>::value, "");
static_assert(std::is_same<void, Something<Baz>::RetT>::value, "");
}
While this does what I think you have asked for, it is not ideal in the sense that if you attempt to instantiate Something<T> with a T that doesn't have an appropriate foo member, you'll get a hard compiler error. It would be better to move the type computation into the template arguments such that you can benefit from the SFINAE rule.
template <typename SomeT,
typename RetT = decltype(std::declval<SomeT>().foo(1))>
struct Something
{
// Can use RetT here ...
};
If you know the argument types to your function call the following should work:
template<typename T>
struct X
{
typedef typename decltype(std::declval<T>.foo(std::declval<int>())) type;
};
If you don't you can still deduce the type of the function pointer and extract the return type:
template<class F>
struct return_type;
template<class C, class R, class... Args>
struct return_type<R(C::*)(Args...)>
{ using type = R; };
template<typename T>
struct X
{
typedef typename return_type<decltype(&T::foo)>::type type;
};
This will fail if T::foo is an overloaded function or member of T.
Unfortunately it is only possible to know the return type of some expression if you know with what arguments you are going to call it (which, unfortunately, often is a different place from where you need to know the return type)...

avoid specifying redundant template parameters which contain templated function pointer

Suppose we have this code:
template <class T, void (*u)(T&)>
void Foo()
{
// store the function u internally . . .
}
There are reasons to do something like this and I won't attempt to go into them. However, is there any way to avoid having to specify type T when calling Foo()? For example, to compile, one normally needs:
Foo<int, MyIntFunction>();
But if this int can be deduced from the function pointer, is this possible:
Foo<MyIntFunction>();
EDIT I'm aware of the solution to pass the actual function pointer in as a function parameter, however this is not desired here as it has some perf drawbacks in intensive loop.
In this example u is not a function pointer, it's a type (the signature of a function pointer). If you want to store a function pointer you need to pass it.
template<class T, class F = void(*)(T&)>
void Foo(F f)
{
// store the function pointer f here
}
called like so:
struct SomeType {};
void bar(SomeType& x);
Foo(&bar);
Is this what you mean to do?
Short answer: I don't think it is possible.
Long one.. When calling a template function, you cannot omit the first parameter and specify the second: the compiler would try to match your MyIntFunction to the template parameter T. Generally, you can specify the first, but omit the second if the compiler can infer the second template parameter. In this case, this is not an option however, because you want to specify the second parameter explicitly.
The second template parameter has a dependency (T) on the first template parameter. Therefore, reversing the order of the template parameters is also not an option.
Your best bet would be to define it in a way similar to what Richard suggested:
template<class T>
void Foo(T f)
{
int a(1);
f(a); // this forces f to be a function taking an int as parameter
}
Here is a dirty implementation which basically does what the OP was asking for. It depends on too many assumptions, but could be at least something to discuss. The idea is to specify in advance all possible types which can serve as function argument, and then deduce this type.
#include<iostream>
template<typename T>
struct TD; //type display
template<typename FunctionType, typename T, typename ... Ts>
struct ArgumentDeduction
{
typedef typename std::conditional<std::is_same<void, typename std::result_of<FunctionType(T)>::type>::value
, T
, typename ArgumentDeduction<FunctionType, Ts ...>::type
>::type type;
};
template<typename FunctionType, typename T>
struct ArgumentDeduction<FunctionType, T>
{
typedef typename std::conditional<std::is_same<void, typename std::result_of<FunctionType(T)>::type>::value
, T
, void
>::type type;
};
template<typename FunctionType
, typename T = typename ArgumentDeduction<FunctionType, int, double>::type >
void foo()
{
TD<T>();
}
struct AvoidConversion
{
struct DummyType{};
template<typename T> DummyType operator()(T x) { return DummyType(); }
};
struct Bar : public AvoidConversion
{
using AvoidConversion::operator();
void operator()(int x);
//void operator()(double x); //try also this
};
int main()
{
foo<Bar>(); //calls the foo<Bar,int> version
}
One main assumption here is the form of the Bar functor, which in principle accepts any type, but has a relevant implementation of type void only for the single allowed type.
Again, I don't think this is rather useful, but I guess this comes closest to the OP's question up to now.
DEMO
EDIT: Otherwise, i.e. without AvoidConversion in the code above, the compiler will perform an implicit conversion and the argument deduction gives true for all types which are convertible into each other (such that, e.g., int is deduced when there is only a function taking double).
If someone sees a way to avoid this ugly AvoidConversion hack and deduce the parameter type somehow more elegant, I would be interested in seeing that.

Match type of inherited member functions

I have the following snipped of code, which does not compile.
#include <iostream>
struct A {
void foo() {}
};
struct B : public A {
using A::foo;
};
template<typename U, U> struct helper{};
int main() {
helper<void (A::*)(), &A::foo> compiles;
helper<void (B::*)(), &B::foo> does_not_compile;
return 0;
}
It does not compile since &B::foo resolves to &A::foo, and thus it cannot match the proposed type void (B::*)(). Since this is part of a SFINAE template that I am using to check for a very specific interface (I'm forcing specific argument types and output types), I would like for this to work independently of inheritances, while keeping the check readable.
What I tried includes:
Casting the second part of the argument:
helper<void (B::*)(), (void (B::*)())&B::foo> does_not_compile;
This unfortunately does not help as the second part is now not recognized as a constant expression, and fails.
I've tried assigning the reference to a variable, in order to check that.
constexpr void (B::* p)() = &B::foo;
helper<void (B::* const)(), p> half_compiles;
This code is accepted by clang 3.4, but g++ 4.8.1 rejects it, and I have no idea on who's right.
Any ideas?
EDIT: Since many comments are asking for a more specific version of the problem, I'll write it here:
What I'm looking for is a way to explicitly check that a class respects a specific interface. This check will be used to verify input arguments in templated functions, so that they respect the contract that those functions require, so that compilation stops beforehand in case the class and a function are not compatible (i.e. type traits kind of checking).
Thus, I need to be able to verify return type, argument type and number, constness and so on of each member function that I request. The initial question was the checking part of the bigger template that I'm using to verify matches.
A working solution to your problem as posted at https://ideone.com/mxIVw3 is given below - see also live example.
This problem is in a sense a follow-up of Deduce parent class of inherited method in C++. In my answer, I defined a type trait member_class that extracts a class from a given pointer to member function type. Below we use some more traits to analyse and then synthesize back such a type.
First, member_type extracts the signature, e.g. void (C::*)() gives void():
template <typename M> struct member_type_t { };
template <typename M> using member_type = typename member_type_t <M>::type;
template <typename T, typename C>
struct member_type_t <T C::*> { using type = T;};
Then, member_class extracts the class, e.g. void (C::*)() gives C:
template<typename>
struct member_class_t;
template<typename M>
using member_class = typename member_class_t <M>::type;
template<typename R, typename C, typename... A>
struct member_class_t <R(C::*)(A...)> { using type = C; };
template<typename R, typename C, typename... A>
struct member_class_t <R(C::*)(A...) const> { using type = C const; };
// ...other qualifier specializations
Finally, member_ptr synthesizes a pointer to member function type given a class and a signature, e.g. C + void() give void (C::*)():
template <typename C, typename S>
struct member_ptr_t;
template <typename C, typename S>
using member_ptr = typename member_ptr_t <C, S>::type;
template <typename C, typename R, typename ...A>
struct member_ptr_t <C, R(A...)> { using type = R (C::*)(A...); };
template <typename C, typename R, typename ...A>
struct member_ptr_t <C const, R(A...)> { using type = R (C::*)(A...) const; };
// ...other qualifier specializations
The two previous traits need more specialization for different qualifiers to be more generic, e.g. const/volatile or ref-qualifiers. There are 12 combinations (or 13 including data members); a complete implementation is here.
The idea is that any qualifiers are transferred by member_class from the pointer-to-member-function type to the class itself. Then member_ptr transfers qualifiers from the class back to the pointer type. While qualifiers are on the class type, one is free to manipulate with standard traits, e.g. add or remove const, lvalue/rvalue references, etc.
Now, here is your is_foo test:
template <typename T>
struct is_foo {
private:
template<
typename Z,
typename M = decltype(&Z::foo),
typename C = typename std::decay<member_class<M>>::type,
typename S = member_type<M>
>
using pattern = member_ptr<C const, void()>;
template<typename U, U> struct helper{};
template <typename Z> static auto test(Z z) -> decltype(
helper<pattern<Z>, &Z::foo>(),
// All other requirements follow..
std::true_type()
);
template <typename> static auto test(...) -> std::false_type;
public:
enum { value = std::is_same<decltype(test<T>(std::declval<T>())),std::true_type>::value };
};
Given type Z, alias template pattern gets the correct type M of the member pointer with decltype(&Z::foo), extracts its decay'ed class C and signature S, and synthesizes a new pointer-to-member-function type with class C const and signature void(), i.e. void (C::*)() const. This is exactly what you needed: it's the same with your original hard-coded pattern, with the type Z replaced by the correct class C (possibly a base class), as found by decltype.
Graphically:
M = void (Z::*)() const -> Z + void()
-> Z const + void()
-> void (Z::*)() const == M
-> SUCCESS
M = int (Z::*)() const& -> Z const& + int()
-> Z const + void()
-> void (Z::*)() const != M
-> FAILURE
In fact, signature S wasn't needed here, so neither was member_type. But I used it in the process, so I am including it here for completeness. It may be useful in more general cases.
Of course, all this won't work for multiple overloads, because decltype doesn't work in this case.
If you simply want to check the existence of the interface on a given type T, then there're better ways to do it. Here is one example:
template<typename T>
struct has_foo
{
template<typename U>
constexpr static auto sfinae(U *obj) -> decltype(obj->foo(), bool()) { return true; }
constexpr static auto sfinae(...) -> bool { return false; }
constexpr static bool value = sfinae(static_cast<T*>(0));
};
Test code:
struct A {
void foo() {}
};
struct B : public A {
using A::foo;
};
struct C{};
int main()
{
std::cout << has_foo<A>::value << std::endl;
std::cout << has_foo<B>::value << std::endl;
std::cout << has_foo<C>::value << std::endl;
std::cout << has_foo<int>::value << std::endl;
return 0;
}
Output (demo):
1
1
0
0
Hope that helps.
Here's a simple class that passes your tests (and doesn't require a dozen of specializations :) ). It also works when foo is overloaded. The signature that you wish to check can also be a template parameter (that's a good thing, right?).
#include <type_traits>
template <typename T>
struct is_foo {
template<typename U>
static auto check(int) ->
decltype( static_cast< void (U::*)() const >(&U::foo), std::true_type() );
// ^^^^^^^^^^^^^^^^^^^
// the desired signature goes here
template<typename>
static std::false_type check(...);
static constexpr bool value = decltype(check<T>(0))::value;
};
Live example here.
EDIT :
We have two overloads of check. Both can take a integer literal as a parameter and because the second one has an ellipsis in parameter list it'll never be the best viable in overload resolution when both overloads are viable (elipsis-conversion-sequence is worse than any other conversion sequence). This lets us unambiguously initialize the value member of the trait class later.
The second overload is only selected when the first one is discarded from overload set. That happens when template argument substitution fails and is not an error (SFINAE).
It's the funky expression on the left side of comma operator inside decltype that makes it happen. It can be ill-formed when
the sub-expression &U::foo is ill-formed, which can happen when
U is not a class type, or
U::foo is inaccesible, or
there is no U::foo
the resulting member pointer cannot be static_cast to the target type
Note that looking up &U::foo doesn't fail when U::foo itself would be ambiguous. This is guaranteed in certain context listed in C++ standard under 13.4 (Address of overloaded function, [over.over]). One such context is explicit type conversion (static_cast in this case).
The expression also makes use of the fact that T B::* is convertible to T D::* where D is a class derived from B (but not the other way around). This way there's no need for deducing the class type like in iavr's answer.
value member is then initialized with value of either true_type or false_type.
There's a potential problem with this solution, though. Consider:
struct X {
void foo() const;
};
struct Y : X {
int foo(); // hides X::foo
};
Now is_foo<Y>::value will give false, because name lookup for foo will stop when it encounters Y::foo. If that's not your desired behaviour, consider passing the class in which you wish to perform lookup as a template parameter of is_foo and use it in place of &U::foo.
Hope that helps.
I suggest using decltype to generically determine the type of the member function pointers:
helper<decltype(&A::foo), &A::foo> compiles;
helper<decltype(&B::foo), &B::foo> also_compiles;
It may seem like a DRY violation, but repeating the name is fundamentally no worse than specifying the type separately from the name.

Can someone explain how to use result_of within template?

I'm trying to create a delayable call object. Something along the lines of (pseudo-code):
template <class FN>
struct delayable_call
{
return-type-of-FN call(); // <-- I'd like to use result_of here.
template<class ArgTypes...>
delayable_call(FN* pFn, ArgTypes... args);
FN* fn;
args-saving-struct;
};
I tried using result_of::type for the return type of call, but get errors during instantiation of the template because apparently the argument types need to be specified separately.
Instantiation:
int foo(bool, double); // function prototype.
delayable_call<int(bool, double)> delayable_foo(foo, false, 3.14); // instantiation
The error messages and documentation I've read about result_of seem to indicate that the argument types must also be specified. So instead of result_of<FN>::type, I'd need to specify result_of<FN(bool, double)>::type. This does actually fix the compilation problem I'm having, but breaks the generality of the template.
So, how can I use result_of with a template parameter when the template parameter represents the function signature?
template <class FN> struct delayable_call;
template<class R, class...Args> delayable_call<R(Args...)>{
typedef R(*)(Args...) pFN;
replace your delayable_call with a specialization, and you will extrace both R and Args.... You need Args... anyhow to store the parameters.
However, a library-strength delayable call will end up using type erasure. The easiest way is a simple std::function<R()> where you shove a lambda into it:
int foo(double);
double x = 7;
std::function<int()> delayed_foo = [x]{ return foo(x); }
and capture by value unless you really, really mean it to capture by reference.
You could deduce R via:
template<typename Fn, typename... Args>
std::function< typename std::result_of<Fn(Args...)>::type()>
make_delayed_call( Fn&& fn, Args&&... args ) {
return [=]{ return fn(std::move(args)...); }
}
which should deduce your R from the callable object and the arguments. This captures everything by copy -- capture by move requires either more boilerplate, or C++14.