Why does the following code not compile under either gcc or clang:
class Foo {
public:
void bar(int) {}
};
template< class T, typename ...Args, void(T::*Member)(Args...) >
void member_dispatch(Args&&... args, void* userdata)
{
T* obj = static_cast<T*>(userdata);
(obj->*Member)(std::forward<Args>(args)...);
}
int main()
{
Foo foo;
member_dispatch<Foo, int, &Foo::bar>(1, &foo);
return 0;
}
See e.g. here.
This question can possibly be merged with this one, though here I get unclear compilation errors from gcc and clang (instead of VS).
When you explicitly specify the types, a parameter pack is greedy. &Foo::bar will be parsed as part of typename ...Args, which causes the error.
The correct way to write this is to put it in the function parameter list, instead of a non-type template parameter.
template< class T, typename ...Args>
void member_dispatch(Args&&... args, void(T::*Member)(Args...), void* userdata)
{
T* obj = static_cast<T*>(userdata);
(obj->*Member)(std::forward<Args>(args)...);
}
int main()
{
Foo foo;
member_dispatch<Foo, int>(1, &Foo::bar, &foo);
return 0;
}
A Better Way:
It would be better to take advantage of C++'s template argument deduction. But here you doesn't put the parameter pact at the end of a function parameter list, which is a non-deduced context. So I suggest you re-order it, so that you don't need to specify the template argument:
template<class T, class K, typename ...Args>
void member_dispatch(K T::*ptr, void* userdata, Args&&... args)
{
T* obj = static_cast<T*>(userdata);
(obj->*ptr)(std::forward<Args>(args)...);
}
int main()
{
Foo foo;
member_dispatch(&Foo::bar, &foo, 1);
return 0;
}
Try using a class template instead of a function template.
There has also been a std syntax proposal "template << auto x >> " for none-type template parameters. Proper implementation will simplify your library syntax.
Related
Is there a way to determine a return type of a member function pointer?
Code sample:
///// my library
void my_func(auto mptr) { // have to use `auto`
// some logic based on a return type of mptr: int, string, A, etc.
}
///// client code
struct A {
int foo();
std::string bar(int);
};
class B{
public:
A func(int, double);
};
// ... and many other classes
my_func(&A::foo);
my_func(&A::bar);
my_func(&B::func);
// ... many other calls of my_func()
I need to "fill in" my_func().
Edit:
I can't use std::result_of/std::invoke_result as I don't know the full list of parameters of mptr. It's not important with which params a method is supposed to be called as I'm not calling it. I would like to avoid creating an object of base class of mptr even if I'm able to determine it (using declval is ok).
You can use partial template specialization to determine the return type of mptr:
template <typename T>
struct ReturnType;
template <typename Object, typename Return, typename... Args>
struct ReturnType<Return (Object::*)(Args...)>
{
using Type = Return;
};
void my_func(auto mptr) {
typename ReturnType<decltype(mptr)>::Type obj;
}
Live Demo
You can write a function that deduces the type of a member function pointer, and returns the deduced return type. Note that only a declaration, and no definition is needed
template <typename C, typename Ret, typename... Args>
auto ret_type(Ret (C::*)(Args...)) -> Ret;
void my_func(auto mptr)
{
using type = decltype(ret_type(mptr));
}
In my opinion, this is also easier to read than the specialization solution.
Here's a demo
You can also account for cv-qualifiers by adding overloads. e.g.
template <typename C, typename Ret, typename... Args>
auto ret_type(Ret (C::*)(Args...) const) -> Ret;
Here's a demo
Assume there is a template function foo() which accepts an arbitrary number of arguments. Given the last argument is always an std::function, how do I implement a foo() template shown below in a way that CbArgs would contain this std::function's parameters?
template<typename... InArgs, typename... CbArgs = ???>
// ^^^^^^^^^^^^
void foo(InArgs... args) { ... }
For example, CbArgs should be {int,int} if invoked like this:
std::function<void(int,int)> cb;
foo(5, "hello", cb);
My first idea was:
template<typename... InArgs, typename... CbArgs>
void foo(InArgs... args, std::function<void(CbArgs...)>) { ... }
But this does not compile:
note: template argument deduction/substitution failed:
note: mismatched types ‘std::function<void(CbArgs ...)>’ and ‘int’
foo(5, "hello", cb);
Question One:
Why doesn't this compile? Why does the template argument deduction fail?
Eventually, I came up this solution:
template<typename... InArgs, typename... CbArgs>
void fooImpl(std::function<void(CbArgs...)>, InArgs... args) { ... }
template<typename... InArgs,
typename CbType = typename std::tuple_element_t<sizeof...(InArgs)-1, std::tuple<InArgs...>>>
void foo(InArgs... args)
{
fooImpl(CbType{}, args...);
}
Here CbType is the last type in InArgs which is std::function. Then a temporary of CbType is passed to fooImpl() where CbArgs are deduced. This works, but looks ugly to me.
Question Two:
I wonder if there is a better solution without having two functions and a temporary instance of CbType?
Why doesn't this compile? Why does the template argument deduction fail?
When a parameter pack is not the last parameter, it cannot be deduced. Telling the compiler the contents of InArgs... will make your foo definition work:
template<typename... InArgs, typename... CbArgs>
void foo(InArgs..., std::function<void(CbArgs...)>) { }
int main()
{
std::function<void(int,int)> cb;
foo<int, const char*>(5, "hello", cb);
}
Alternatively, as you discovered in your workaround, simply put InArgs... at the end and update your foo invocation:
template<typename... InArgs, typename... CbArgs>
void foo(std::function<void(CbArgs...)>, InArgs...) { }
int main()
{
std::function<void(int,int)> cb;
foo(cb, 5, "hello");
}
I wonder if there is a better solution without having two functions and a temporary instance of CbType?
Here's a possible way of avoiding the unnecessary temporary instance but using your same mechanism for the deduction of CbArgs...: simply wrap CbType in an empty wrapper, and pass that to fooImpl instead.
template <typename T>
struct type_wrapper
{
using type = T;
};
template<typename... InArgs, typename... CbArgs>
void fooImpl(type_wrapper<std::function<void(CbArgs...)>>, InArgs&&...) { }
template<typename... InArgs,
typename CbType =
std::tuple_element_t<sizeof...(InArgs)-1,
std::tuple<std::remove_reference_t<InArgs>...>>>
void foo(InArgs&&... args)
{
fooImpl(type_wrapper<CbType>{}, std::forward<InArgs>(args)...);
}
Additional improvements:
The typename after typename CbType = was unnecessary - it was removed.
args... should be perfectly-forwarded to fooImpl to retain its value category. Both foo and fooImpl should take args... as a forwarding-reference.
wandbox example
Note that there is a proposal that would make dealing with non-terminal parameter packs way easier: P0478R0 - "Template argument deduction for non-terminal
function parameter packs". That would make your original implementation work as intended.
I have a function that calls a callback function that accepts a movable-only type (for example unique_ptr).
template <typename Function>
void foo(const Function& function) {
BOOST_CONCEPT_ASSERT((
boost::UnaryFunction<Function, void, std::unique_ptr<Bar>));
auto bar = std::make_unique<Bar>();
...
function(std::move(bar));
}
Trying to compile this code, I get a message that the BOOST_CONCEPT_ASSERT line tries to copy the unique_ptr. If I remove the line, the code works fine. It seems that the Boost.Concept library does not support move semantics. Is there any workaround for this without writing my own concept class (which, incidentally, would not be very simple to support both lvalues and rvalues as their arguments).
That's correct. Unfortunately, UnaryFunction as a concept is written as:
BOOST_concept(UnaryFunction,(Func)(Return)(Arg))
{
BOOST_CONCEPT_USAGE(UnaryFunction) { test(is_void<Return>()); }
private:
void test(boost::mpl::false_)
{
f(arg); // "priming the pump" this way keeps msvc6 happy (ICE)
Return r = f(arg);
ignore_unused_variable_warning(r);
}
void test(boost::mpl::true_)
{
f(arg); // <== would have to have std::move(arg)
// here to work, or at least some kind of
// check against copy-constructibility, etc.
}
#if (BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4) \
&& BOOST_WORKAROUND(__GNUC__, > 3)))
// Declare a dummy construktor to make gcc happy.
// It seems the compiler can not generate a sensible constructor when this is instantiated with a refence type.
// (warning: non-static reference "const double& boost::UnaryFunction<YourClassHere>::arg"
// in class without a constructor [-Wuninitialized])
UnaryFunction();
#endif
Func f;
Arg arg;
};
Since arg is passed by lvalue, there's no way to get that to work with Boost.Concepts. Directly. You could write a hack though. Since we're just calling checking that f(arg) is valid, we could construct a local type for arg that is convertible to unique_ptr<Bar>. That is:
template <typename Function>
void foo(Function f)
{
struct Foo {
operator std::unique_ptr<int>();
};
BOOST_CONCEPT_ASSERT((
boost::UnaryFunction<Function, void, Foo>));
f(std::make_unique<int>(42));
}
Or more generally:
template <typename T>
struct AsRvalue {
operator T(); // no definition necessary
};
template <typename Function>
void foo(Function f)
{
BOOST_CONCEPT_ASSERT((
boost::UnaryFunction<Function, void, AsRvalue<std::unique_ptr<int>>>));
f(std::make_unique<int>(42));
}
That compiles for me on gcc and clang (though gives a warning on clang about unused typedefs). However, at that point, it may be clearer to just write out your own concept to get it to work. Something like Piotr's would be easiest.
#include <type_traits>
#include <utility>
template <typename...>
struct voider { using type = void; };
template <typename... Ts>
using void_t = typename voider<Ts...>::type;
template <typename, typename = void_t<>>
struct is_callable : std::false_type {};
template <typename F, typename... Args>
struct is_callable<F(Args...), void_t<decltype(std::declval<F>()(std::declval<Args>()...))>> : std::true_type {};
//...
static_assert(is_callable<Function&(std::unique_ptr<Bar>)>{}, "Not callable");
DEMO
In this example a function is passed to an implicitly instantiated function template.
// Function that will be passed as argument
int foo() { return 0; }
// Function template to call passed function
template<typename F>
int call(F f) {
return f();
}
template<typename F, typename A>
int call(F f, A a) {
return f(a);
}
int a = call(foo);
We can break this code by adding an overload for foo().
int foo(int i) { return 0; }
The name "foo" is now ambiguous and the example will no longer compile. This can be made to compile by explicitly providing function pointer type info.
int (*func_takes_void)() = foo;
int a = call(func_takes_void);
int (*func_takes_int)(int) = foo;
int b = call(func_takes_int, 0);
http://coliru.stacked-crooked.com/a/e08caf6a0ac1e6b9
Is it possible to instead deduce the function pointer types? If so, why does my attempt below not work and what is the right way to do this?
If this is not possible, a good answer would explain why.
Attempt thus far
A human can see which foo() is intended in the two calls by inspecting the definitions of call<>() but that info is not available to the compiler for overload resolution. Still, the information is all there, it just needs to be pulled into the function template signature. This may be possible with expression SFINAE.
In pseudo code we want this:
template<IgnoreThis, typename ReturnType>
struct expr_check
{
typedef ReturnType type;
}
template<typename F>
expr_check<expression requiring F have correct signature, result_of<F>::type>::type
call(F f);
Here is that idea worked out in real code.
http://coliru.stacked-crooked.com/a/a3ce828d6cb16c2d
The function template signatures are:
template<typename F>
typename expr_check<sizeof(declval<F>()()), typename func_ptr_result<F>::type>::type
call(F f);
template<typename F, typename A>
typename expr_check<sizeof(declval<F>()(declval<A>())), typename func_ptr_result<F>::type>::type
call(F f, A a);
What I currently have does not compile. From the compiler output you can see that on both attempts to instantiate the function template there is substitution failure on one call<>() overload and the other simply gives an opaque "couldn't deduce template parameter".
(The colirus were compiled as C++03 but C++11 answers are fine.)
My suspicion is that while instantiating call<>(), foo() is not being called and C++ simply does not provide for overload resolution of foo() in this context. It doesn't matter that it can be proven that one foo() overload is the correct one, C++ just doesn't mandate overload resolution here. On the other hand, overload resolution isn't limited to a function being called. A function pointer of appropriate type gets to select overloads of foo().
Related questions
There are a few questions asking about overloading on function pointer type. It looks like this can't be done. I didn't find any questions trying to do this through expression SFINAE.
This seems to be the closest related question.
Is there a way to deduce the value of a function pointer template parameter?
Bonus pedantry
Is "function pointer" the correct phrase to have used in the title? Would "function reference" have been more accurate?
The closest you can get is probably this:
struct sfoo
{
template<typename... args>
void operator() (args&&... a)
{
foo(std::forward<args>(a)...);
}
};
and pass sfoo (or sfoo()) instead of foo around.
That is, create a function object type that encapsulates the entire overload set in the templatized operator().
Then instead of overload resolution over a template argument, which does not exist, you get a template instantiation over the same argument, which is OK.
As has been mentioned before, SFINAE doesn't work because the names of overloaded functions have no definite type in C++, therefore template parameter substitution doesn't even happen at this stage.
However, in your example, the problem is arguably not that you have too many overloads of "foo", but too few overloads of "call". Just provide both the templates with typename F and the ones that expect a function pointer. The compiler will now be able to do the right thing depending on context:
#include <iostream>
// Functions
int foo() { return 0; }
int foo(int) { return 1; }
// Function object
struct Foo
{
int operator()() const { return 2; }
int operator()(int) const { return 3; }
};
// Higher-order functions / templates
template<typename F>
int call(F f) {
return f();
}
int call(int (*f)()) {
return f();
}
template<typename F, typename A>
int call(F f, A a) {
return f(a);
}
template<typename A>
int call(int (*f)(A), A a) {
return f(a);
}
int main()
{
int a = call(foo)
, b = call(foo, 0)
, c = call(Foo())
, d = call(Foo(), 0);
std::cout << a << ',' << b << ',' << c << ',' << d << '\n'; // 0,1,2,3
}
The call overloads can be made more generic by adding return type deduction. In C++11, this is possible even with function objects by using decltype rsp. result_of. For brevity, I will post only the new function signatures, as the bodies don't need to be changed in this case:
template<typename F>
auto call(F f) -> decltype(f());
template<typename R>
R call(R (*f)());
template<typename F, typename A>
auto call(F f, A a) -> decltype(f(a));
template<typename R, typename A>
R call(R (*f)(A), A a);
I'm writing a generalized function wrapper, that can wrap any function into a lua-style call, which has the form
int lua_function( lua_State *L)
And I wish the wrapper function is generated on-the-fly, so I'm thinking of passing the function as a template argument. This is trivial if you know the number (e.g, 2) of arguments:
template <typename R, typename Arg1, typename Arg2, R F(Arg1, Args)>
struct wrapper
However, I don't know the number, so I beg for variadic template argument for help
// This won't work
template <typename R, typename... Args, R F(Args...)>
struct wrapper
The above won't compile, since variadic argument has to be the last one. So I use two level template, the outer template captures types, the inner template captures the function:
template <typename R, typename... Args>
struct func_type<R(Args...)>
{
// Inner function wrapper take the function pointer as a template argument
template <R F(Args...)>
struct func
{
static int call( lua_State *L )
{
// extract arguments from L
F(/*arguments*/);
return 1;
}
};
};
That works, except that to wrap a function like
double sin(double d) {}
the user has to write
func_type<decltype(sin)>::func<sin>::apply
which is tedious.
The question is: is there any better, user-friendlier way to do it? (I can't use a function template to wrap the whole thing, coz a function parameter can't be used as a template argument.)
Things like std::function and std::result_of use the following technique to do what you want regarding variadic templates:
template<typename Signature>
struct wrapper; // no base template
template<typename Ret, typename... Args>
struct wrapper<Ret(Args...)> {
// instantiated for any function type
};
You could expand the above to add a non-type Ret(&P)(Args...) template parameter (pointers to function work just as well) but you'd still need a decltype at the user level, i.e. wrapper<decltype(sin), sin>::apply. Arguably it would be a legitimate use of the preprocessor if you decide to use a macro to remove the repetition.
template<typename Sig, Sig& S>
struct wrapper;
template<typename Ret, typename... Args, Ret(&P)(Args...)>
struct wrapper<Ret(Args...), P> {
int
static apply(lua_State*)
{
// pop arguments
// Ret result = P(args...);
// push result & return
return 1;
}
};
// &wrapper<decltype(sin), sin>::apply is your Lua-style wrapper function.
The above compiles with gcc-4.5 at ideone.
Good luck with implementing the apply that (variadically) pops the arguments (leave me a comment if you open a question about that). Have you considered using Luabind?
As #Juraj says in his comment, the function pointer can be a template argument, see the following simple example:
#include <iostream>
#include <boost/typeof/typeof.hpp>
void f(int b, double c, std::string const& g)
{
std::cout << "f(): " << g << std::endl;
}
template <typename F, F* addr>
struct wrapper
{
void operator()()
{
std::string bar("bar");
(*addr)(1, 10., bar);
}
};
int main(void)
{
wrapper<BOOST_TYPEOF(f), &f> w;
w();
return 0;
}
working version: http://www.ideone.com/LP0TO
I'm using BOOST_TYPEOF as normally I always provide examples in the current standard, but it does something similar to decltype. Is this what you were after?