functions as template argument, plus variadic template argument - c++

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?

Related

Get return type of a function pointer [duplicate]

I think code will better illustrate my need:
template <typename F>
struct return_type
{
typedef ??? type;
};
so that:
return_type<int(*)()>::type -> int
return_type<void(*)(int,int)>::type -> void
I know of decltype and result_of but they need to have arguments passed. I want to deduce the return type of a function pointer from a single template parameter. I cannot add the return type as a parameter, because that's exactly what I want to hide here...
I know there's a solution in boost, but I can't use it, and an attempt to dig it out from boost resulted in a spectacular failure (as it often does).
C++11 solutions welcome (as long as supported in VS2012).
If you can use variadic templates (November '12 CTP), this should work:
template <class F>
struct return_type;
template <class R, class... A>
struct return_type<R (*)(A...)>
{
typedef R type;
};
Live example.
If you can't use variadic templates, you'll have to provide specific specialisations for 0, 1, 2, ... parameters (by hand or preprocessor-generated).
EDIT
As pointed out in the comments, if you want to work with variadic functions as well, you'll have to add one extra partial specialisation (or one for each parameter count in the no-variadic-templates case):
template <class R, class... A>
struct return_type<R (*)(A..., ...)>
{
typedef R type;
};
It has been a while since the question has been asked. For C++17, there is an interesting option. However, the syntax is a bit different from what was originally asked, but the result (a type) is the same.
First, we need a helper function. As you see here, the function accepts a function pointer and returns an object of type R. We need this only for a decltype statement and therefore this function will never be called, so a forward declaration is sufficient.
template<typename R, typename... ARGS>
static R return_type(R (*)(ARGS...)); // forward declaration only for decltype
The trick is to provide the function pointer as a template auto parameter, which is forwarded to a decltype statement:
template<auto FUNCTION_POINTER>
using ReturnType = decltype(return_type(FUNCTION_POINTER));
Now it is easy to get the return type:
#include <iostream>
#include <type_traits>
template<typename R, typename... ARGS>
static R return_type(R (*)(ARGS...)); // forward declaration only for decltype
template<auto FUNCTION_POINTER>
using ReturnType = decltype(return_type(FUNCTION_POINTER));
int func1(char c, int i, long l); // also here only forward declarations needed
void func2(unsigned u, float f);
double func3(bool b);
int main()
{
std::cout << std::is_same_v<int, ReturnType<func1>> << std::endl;
std::cout << std::is_same_v<void, ReturnType<func2>> << std::endl;
std::cout << std::is_same_v<double, ReturnType<func3>> << std::endl;
std::cout << std::is_same_v<void, ReturnType<func1>> << std::endl;
}
You can try the complete example in Wandbox: https://wandbox.org/permlink/5akL0MQDoDuJlQNY

how to get a return type of a member function pointer

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

Generate function with signature of pointer's type passed to template

I want to create a generator which for each pointer to function will create a static function to which the pointer can point to:
template <auto &PtrToIsrHandler, auto MemberFunction> struct enable_member_isr_handler
{
using TypeOfCFunPtr = std::remove_reference_t<decltype(PtrToIsrHandler)>;
using TypeOfCFunPointed = std::remove_pointer_t<TypeOfCFunPtr>;
using RetType = std::invoke_result_t<TypeOfCFunPointed>;
static RetType isr_handler(/* dunno what to put here */)
{
return /* call MemberFunction here somehow */;
}
enable_member_isr_handler()
{
PtrToIsrHandler = isr_handler;
}
};
In the parameter list of the isr_handler method I tried to put a tuple by using:
template <typename T> struct get_parameters;
template <typename Ret, typename... Args> struct get_parameters<Ret(Args...)>
{
using args_t = std::tuple<Args...>;
};
But I get then:
error: invalid conversion from void (*)(get_parameters<void()>)}’ to ‘void (*)()’
How can I make it in such a way that PtrToIsrHandler could be a valid pointer to isr_handler?
As mentioned in my comment, one approach to get the argument list is to use partial specialization and forward the type of the passed in member function. The same approach can be used on free functions as well.
#include <iostream>
template <auto MemberFunction, class MemberFunctionType>
struct handler_impl;
template <auto MemberFunction, class ReturnType, class ClassType, class... Args>
struct handler_impl<MemberFunction, ReturnType(ClassType::*)(Args...)> {
// here you have access to return-type, class-type and args
static ReturnType call_on_instance(ClassType& obj, Args... args) {
return (obj.*MemberFunction)(args...);
}
};
template <auto MemberFunction>
using handler = handler_impl<MemberFunction, decltype(MemberFunction)>;
struct Foo {
int print(int x) {
std::cout << x*x << std::endl;
return x;
}
};
int main() {
Foo f;
handler<&Foo::print>::call_on_instance(f, 7);
}
One thing to keep in mind here is that we are not using perfect forwarding. The easiest approach is to simply make call_on_instance a template function, then we don't really need to care about the arguments and return value, we can let the compiler deduce it.
Another option is to use the approach I showed above and use a static_assert to make sure the argument list passed in is valid, and thus give a better error message when used in the wrong way.

Create object from class name using a string in C++

I have a Base class:
class Base() {
public:
Base(int, int);
~Base();
};
I have multiple classes that inherit from Base:
class childA : public Base {
public:
childA(int, int, string);
~childA();
};
childA::childA(int x, int y, string str) : Base (x, y)
{
// do something here
}
Same for childB, childC, etc
I want to know if it's possible to create childA, childB or childC using a string. I heard about variadic tempaltes but I don't really understand how to use it.
Variadic template is a template, which can take an arbitrary number of template arguments of any type. Both the functions could be variadic since dawn of C language (printf function, for example), then macros and now - templates.
You can declare it like this:
template<typename... Arguments> class Variadic;
then specialize it with any number of arguments, including zero:
Variadic<double> instance;
Variadic<double, std::string> instance;
Variadic<> instance;
Then you may use the argument list, known as argument pack, like this:
template<typename... Arguments> void SampleFunction(Arguments... parameters);
Just as in case of variadic functions, the argument pack can be preceded by concrete arguments:
template<typename First, typename... Rest> class BunchOfValues;
There is classic example of variadic template in STL: std::tuple. Some compilers do not support this feature fully or do not support at all, and in their case tuple is implemented through metaprogramming and macro definitions.
There is no direct way in C++ to select particular argument from the list, like it is possible with variadic functions. It's possible to use recursion to iterate through them in one direction:
template<typename T> foo(T first)
{
// do something;
}
template<typename T, typename U, typename ... Args> foo(T first, U second, Args... Rest)
{
// do something with T
foo(second, Rest...);
}
Usually iteration would rely on function overloading, or - if the function can simply pick one argument at a time - using a dumb expansion marker:
template<typename... Args> inline void pass(Args&&...) {}
which can be used as follows:
template<typename... Args> inline void expand(Args&&... args) {
pass( some_function(args)... );
}
expand(42, "answer", true);
which will expand to something like:
pass( some_function(arg1), some_function(arg2), some_function(arg3) etc... );
The use of this "pass" function is necessary, since the expansion of the argument pack proceeds by separating the function call arguments by commas, which are not equivalent to the comma operator. some_function(args)...; will never work. Moreover, this above solution will only work when the return type of some_function is not void. Furthermore, the some_function calls will be executed in an unspecified order, because the order of evaluation of function arguments is undefined. To avoid the unspecified order, brace-enclosed initializer lists can be used, which guarantee strict left-to-right order of evaluation. To avoid the need for a not void return type, the comma operator can be used to always yield 1 in each expansion element.
struct pass {
template<typename ...T> pass(T...) {}
};
pass{(some_function(args), 1)...};
The number of arguments in argument pack can be determined by sizeof...(args) expression.
As of creating initializers that use calls name it is possible only if name is defined at time of writing the code. There stingizer operator # in preprocessor that can be used, e.g.
#define printstring( x ) printf(#x "\n")
printstring( This a dumb idea );
will generate code (assuming that C++ automatically joins string literals):
printf("This a dumb idea \n")
You can declare something like this:
template<typename T> class moniker
{
public:
moniker(const char* tname);
}
#define declare_moniker(type, name) moniker<type> name(#type)
How would variadic macro definitions and variadic template interact? I'm not sure. Compiler I have at hand failed, but it isn't C++11. Try that, if interested.
There might be typeid operator supporeted, depending on compiler settings.
const std::type_info& ti1 = typeid(A);
std::type_info got method name(), but string it returns is implementation dependant: http://en.cppreference.com/w/cpp/types/type_info/name
In c++14 you could create some helper struct to determine each character of the string you pass at compile-time and to forward it to a type. However string you pass need to be stored in variable with linkage to let compiler to use it as a non-type template parameter:
#include <utility>
#include <type_traits>
template <char... Cs>
struct string_literal { };
template <class T, T &, class>
struct make_string_literal_impl;
template <class T, T &Cs, std::size_t... Is>
struct make_string_literal_impl<T, Cs, std::index_sequence<Is...>> {
using type = string_literal<Cs[Is]...>;
};
template <class T, T &>
struct make_string_literal;
template <class T, std::size_t N, T (&Cs)[N]>
struct make_string_literal<T[N], Cs>: make_string_literal_impl<T[N], Cs, std::make_index_sequence<N>> {
};
struct Base {
Base(int, int) { }
~Base() { }
};
template <class>
struct Child: Base {
using Base::Base;
};
constexpr char const str[] = "abc";
int main() {
Child<make_string_literal<decltype(str), str>::type> c(1, 1);
}
[live demo]

Deducing a function pointer return type

I think code will better illustrate my need:
template <typename F>
struct return_type
{
typedef ??? type;
};
so that:
return_type<int(*)()>::type -> int
return_type<void(*)(int,int)>::type -> void
I know of decltype and result_of but they need to have arguments passed. I want to deduce the return type of a function pointer from a single template parameter. I cannot add the return type as a parameter, because that's exactly what I want to hide here...
I know there's a solution in boost, but I can't use it, and an attempt to dig it out from boost resulted in a spectacular failure (as it often does).
C++11 solutions welcome (as long as supported in VS2012).
If you can use variadic templates (November '12 CTP), this should work:
template <class F>
struct return_type;
template <class R, class... A>
struct return_type<R (*)(A...)>
{
typedef R type;
};
Live example.
If you can't use variadic templates, you'll have to provide specific specialisations for 0, 1, 2, ... parameters (by hand or preprocessor-generated).
EDIT
As pointed out in the comments, if you want to work with variadic functions as well, you'll have to add one extra partial specialisation (or one for each parameter count in the no-variadic-templates case):
template <class R, class... A>
struct return_type<R (*)(A..., ...)>
{
typedef R type;
};
It has been a while since the question has been asked. For C++17, there is an interesting option. However, the syntax is a bit different from what was originally asked, but the result (a type) is the same.
First, we need a helper function. As you see here, the function accepts a function pointer and returns an object of type R. We need this only for a decltype statement and therefore this function will never be called, so a forward declaration is sufficient.
template<typename R, typename... ARGS>
static R return_type(R (*)(ARGS...)); // forward declaration only for decltype
The trick is to provide the function pointer as a template auto parameter, which is forwarded to a decltype statement:
template<auto FUNCTION_POINTER>
using ReturnType = decltype(return_type(FUNCTION_POINTER));
Now it is easy to get the return type:
#include <iostream>
#include <type_traits>
template<typename R, typename... ARGS>
static R return_type(R (*)(ARGS...)); // forward declaration only for decltype
template<auto FUNCTION_POINTER>
using ReturnType = decltype(return_type(FUNCTION_POINTER));
int func1(char c, int i, long l); // also here only forward declarations needed
void func2(unsigned u, float f);
double func3(bool b);
int main()
{
std::cout << std::is_same_v<int, ReturnType<func1>> << std::endl;
std::cout << std::is_same_v<void, ReturnType<func2>> << std::endl;
std::cout << std::is_same_v<double, ReturnType<func3>> << std::endl;
std::cout << std::is_same_v<void, ReturnType<func1>> << std::endl;
}
You can try the complete example in Wandbox: https://wandbox.org/permlink/5akL0MQDoDuJlQNY