Get function parameters count [duplicate] - c++

This question already has an answer here:
Get function arity from template parameter
(1 answer)
Closed 6 years ago.
I'm wondering if there is a way in C++11 to get the number of arguments of a function?
For example for the function foo I want argCount to be 3.
void foo(int a, int b, int c) {}
int main() {
size_t argCount = MAGIC(foo);
}

You can get that information by using a variadic function template.
#include <iostream>
template <typename R, typename ... Types> constexpr size_t getArgumentCount( R(*f)(Types ...))
{
return sizeof...(Types);
}
//----------------------------------
// Test it out with a few functions.
//----------------------------------
void foo(int a, int b, int c)
{
}
int bar()
{
return 0;
}
int baz(double)
{
return 0;
}
int main()
{
std::cout << getArgumentCount(foo) << std::endl;
std::cout << getArgumentCount(bar) << std::endl;
std::cout << getArgumentCount(baz) << std::endl;
return 0;
}
Output:
3
0
1
See it working at http://ideone.com/oqF8E8.
Update
Barry suggested use of:
template <typename R, typename ... Types>
constexpr std::integral_constant<unsigned, sizeof ...(Types)> getArgumentCount( R(*f)(Types ...))
{
return std::integral_constant<unsigned, sizeof ...(Types)>{};
}
With this, you can get the number of argument by using:
// Guaranteed to be evaluated at compile time
size_t count = decltype(getArgumentCount(foo))::value;
or
// Most likely evaluated at compile time
size_t count = getArgumentCount(foo).value;

Yes, it can be easily done:
#include <cstddef>
#include <iostream>
template <class R, class... ARGS>
struct function_ripper {
static constexpr size_t n_args = sizeof...(ARGS);
};
template <class R, class... ARGS>
auto constexpr make_ripper(R (ARGS...) ) {
return function_ripper<R, ARGS...>();
}
void foo(int, double, const char*);
void check_args() {
constexpr size_t foo_args = decltype(make_ripper(foo))::n_args;
std::cout << "Foo has " << foo_args << " arguments.\n";
}

This doesn't really make sense for several reasons.
For starters, what would this really be good for? You might be looking for some sort of reflection, but that doesn't (yet) exist in C++.
The main reason this doesn't make sense, however, is overload sets:
void f(int);
void f(int, int);
std::cout << MAGIC(f); // what should this print??

Related

How to get number of function arguments from `decltype(<funtion>)`?

Let's say I have the following function declaration:
template<typename signature>
int foo();
Given the above-mentioned function, is it possible to define foo in such a way, so that it returns the number of function arguments that were passed in the decltype template parameter?
So the example usage might look like:
int bar(int a, int b)
{
return a + b;
}
int jar(int a)
{
return a * a;
}
int main()
{
std::cout << foo<decltype(bar)>() << std::endl; // Desired output: 2
std::cout << foo<decltype(jar)>() << std::endl; // Desired output: 1
}
Edit:
Thanks, everyone for the replies. They do seem to work. However, I forgot to mention one more use case.
Let's say I want to get the number of arguments of the following function:
int __stdcall car(int a, int b, int c)
{
return a * b + c;
}
The answers so far do not seem to work with this kind of function that uses __stdcall convention.
Any idea why and what can be done about it?
For that(i.e. with decltype), the given foo is not enough. You need something like the followings traits.
template<typename> struct funtion_args final {};
template<typename ReType, typename... Args>
struct funtion_args<ReType(Args...)> final
{
static constexpr std::size_t noArgs = sizeof...(Args);
};
Used sizeof... operator on the variadic template arguments, to get the no of arguments.
And then you can get the argument count directly like
std::cout << funtion_args<decltype(bar)>::noArgs << "\n"; // output: 2
or pack into the foo
template<typename signature>
constexpr std::size_t foo() noexcept
{
return funtion_args<signature>::noArgs;
}
(See Live Demo)
Better Approach
If you want less typing(i.e. without decltype), a more convenient way of getting the arguments count of a free-function, you could do the following
template <typename ReType, typename... Args>
constexpr auto foo(ReType(*)(Args...)) noexcept
{
return sizeof...(Args);
}
Now you could conveniently call the foo with other functions as arguments
std::cout << foo(bar) << "\n"; // output: 2
(See Live Demo)
Sure, just have foo() call on a suitable trait type. For example:
template <typename T>
struct foo_helper;
template <typename T, typename... Args>
struct foo_helper<T(Args...)> {
static constexpr std::size_t arg_count = sizeof...(Args);
};
template <typename T>
std::size_t foo() {
return foo_helper<T>::arg_count;
}

template type deduction of template parameter

I know, that there exists the possibility for automatic type deduction of function templates, given a particular function parameter, but does there also exist such a method for non type template parameters?
Example:
#include <iostream>
template<typename T, T val>
void func_a(void) {
std::cout << val << std::endl;
}
template<typename T>
void func_b(T val) {
std::cout << val << std::endl;
}
int main(void) {
func_a<uint32_t, 42u>();
//func_a<42u>(); //This line doesn't work
func_b(42u);
return 0;
}
So I don't want to give each time the template argument type uint32_t every time, when I call func_a(). Does there such a method exist in C++17 or below?
I am using g++ v.7.3 and c++17.
In C++17, you can use auto:
template<auto val>
void func_a(void) {
std::cout << val << std::endl;
}
int main(void) {
func_a<42u>();
return 0;
}
Given a +1 for the C++17 solution, a better-than-nothing C++11/C++14 solution can be the use of a macro to activate decltype() over the argument.
By example, with the macro
#define func_a_macro(val) func_a<decltype(val), val>
or better, as suggested by liliscent, to avoid problems with references
#define func_a_macro(val) \
func_a<std::remove_reference<decltype(val)>::type, val>
you can call
func_a_macro(42u)();
p.s.: I know... I know... macros are distilled evil... but sometime are useful.
C++14 solution with no macros:
template<int N> auto Int = std::integral_constant<int, N>{};
template<class T, T n>
constexpr auto foo(std::integral_constant<T, n> x)
{
std::cout << x.value << std::endl;
}
int main()
{
foo(Int<6>);
}
c++11:
template<int N> using Int = std::integral_constant<int, N>;
template<class T, T n>
constexpr void foo(std::integral_constant<T, n> x)
{
std::cout << x.value << std::endl;
}
int main()
{
foo(Int<6>());
}

how to expand a statement multiple times based on template variable arguments

I have the following pseudo code:
template <typename... Ts>
void f(int index) {
std::vector<std::function<void(void)>> funcs;
funcs.push_back([](){ std::cout << typeid(type_1).name() << std::endl; });
funcs.push_back([](){ std::cout << typeid(type_2).name() << std::endl; });
funcs.push_back([](){ std::cout << typeid(type_3).name() << std::endl; });
funcs.push_back([](){ std::cout << typeid(type_4).name() << std::endl; });
funcs[index]();
}
Imagine that the Ts... parameter pack holds type_1, type_2, type_3 and type_4.
how can I expand the parameter pack in order to achieve something like this? I mean - how can I get 4 push_back() calls if there are 4 parameters in the template pack, and also have the different types in the different lambdas? I don't know the syntax..
And can I actually get some sort of an array of such functions at compile time, so there are no push_backs at runtime?
C++17 solution is ok, but C++14 is best.
For C++17, something like this, I suppose
(funcs.push_back([](){ std::cout << typeid(Ts).name() << std::endl; }), ...);
or, better (IMHO), using emplace_back()
(funcs.emplace_back([](){ std::cout << typeid(Ts).name() << std::endl; }), ...);
But remeber that is
std::vector<std::function<void(void)>>
not
std::vector<std::function<void>>
In C++14 (and C++11) you can obtain something similar with the trick of intialization of the unused array; the function can be written as
template <typename ... Ts>
void f (int index)
{
using unused = int[];
std::vector<std::function<void(void)>> funcs;
(void)unused { 0, (funcs.emplace_back([]()
{ std::cout << typeid(Ts).name() << std::endl; }), 0)... };
funcs[index]();
}
Update.
From re-reading the question I think you just want to call the function once for the I'th type.
I which case it's trivial at compile time:
#include <array>
#include <type_traits>
#include <iostream>
#include <string>
template <class T>
void show_type()
{
std::cout << typeid(T).name() << std::endl;
}
template <typename... Ts>
void f(int index) {
using function_type = void(*)();
constexpr auto size = sizeof...(Ts);
constexpr std::array<function_type, size> funcs =
{
&show_type<Ts>...
};
funcs[index]();
}
int main()
{
for(int i = 0 ; i < 3 ; ++i)
f<int, double, std::string>(i);
}
example output:
i
d
NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Something along these lines, perhaps:
template <typename... Ts>
void f(int index) {
int i = 0;
auto _ = {
(index == i++ ? ((std::cout << typeid(Ts).name() << std::endl) , 0) : 0) ...
};
}
Demo
If all you want to do is do something for the nth type in a template parameter pack, where n is a runtime variable, then the vector + function approach isn't really great. Better to add an index sequence in there and fold:
template <typename T> struct tag_t { using type = T; };
template <typename T> constexpr inline tag_t<T> tag{};
template <class F, size_t... Is, typename... Tags>
void match(F f, size_t i, std::index_sequence<Is...>, Tags... tags) {
auto inner = [&](auto tag) { f(tag); return true; };
bool matched = ((i == Is && inner(tags)) || ...);
if (!matched) {
// failure case?
}
}
template <typename... Ts, class F>
void match(F f, size_t i) {
return match(f, i, std::index_sequence_for<Ts...>(), tag<Ts>... );
}
template <typename... Ts>
void foo(int index) {
match<Ts...>([](auto tag){
std::cout << typeid(typename decltype(tag)::type).name() << std::endl;
}, index);
}
This construction allows you to add a failure case, where you might call the passed-in function with some special type:
struct failure { };
template <class F, size_t... Is, typename... Tags>
void match(F f, size_t i, std::index_sequence<Is...>, Tags... tags) {
auto inner = [&](auto tag) { f(tag); return true; };
bool matched = ((i == Is && inner(tags)) || ...);
if (!matched) {
f(failure{});
}
}
template <typename... Ts>
void foo(int index) {
match<Ts...>(overload(
[](auto tag){
std::cout << typeid(typename decltype(tag)::type).name() << std::endl;
},
[](failure ) { /* ... */ }
), index);
}

C++ function call wrapper with function as template argument

I'm trying to create a generic wrapper function that takes a function as a template argument and takes the same arguments as that function as its arguments. For example:
template <typename F, F func>
/* return type of F */ wrapper(Ts... Args /* not sure how to get Ts*/)
{
// do stuff
auto ret = F(std::forward<Ts>(args)...);
// do some other stuff
return ret;
}
The solution needs to be castable to a function pointer with the same type as func so that I can pass it to a C api. In other words, the solution needs to be a function and not a function object. Most importantly, I need to be able to do work in the wrapper function.
If the inline comments aren't clear, I'd like to be able to do something like the following:
struct c_api_interface {
int (*func_a)(int, int);
int (*func_b)(char, char, char);
};
int foo(int a, int b)
{
return a + b;
}
int bar(char a, char b, char c)
{
return a + b * c;
}
c_api_interface my_interface;
my_interface.func_a = wrapper<foo>;
my_interface.func_b = wrapper<bar>;
I looked for related posts and found these, but none of them are quite what I'm trying to do. Most of these posts concern function objects. Is what I'm trying to do even possible?
Function passed as template argument
Function wrapper via (function object) class (variadic) template
How does wrapping a function pointer and function object work in generic code?
How do I get the argument types of a function pointer in a variadic template class?
Generic functor for functions with any argument list
C++ Functors - and their uses
In response to the first 2 responses, I edited the question to make it clear that I need to be able to do work in the wrapper function (i.e. modify some global state before and after the call to the wrapped function)
template<class F, F f> struct wrapper_impl;
template<class R, class... Args, R(*f)(Args...)>
struct wrapper_impl<R(*)(Args...), f> {
static R wrap(Args... args) {
// stuff
return f(args...);
}
};
template<class F, F f>
constexpr auto wrapper = wrapper_impl<F, f>::wrap;
Use as wrapper<decltype(&foo), foo>.
#include <utility>
#include <iostream>
struct c_api_interface { int (*func_a)(int, int); int (*func_b)(char, char, char); };
int foo(int a, int b) { return a + b; }
int bar(char a, char b, char c) { return a + b * c; }
template<typename Fn, Fn fn, typename... Args>
typename std::result_of<Fn(Args...)>::type
wrapper(Args... args) {
std::cout << "and ....it's a wrap ";
return fn(std::forward<Args>(args)...);
}
#define WRAPIT(FUNC) wrapper<decltype(&FUNC), &FUNC>
int main() {
c_api_interface my_interface;
my_interface.func_a = WRAPIT(foo);
my_interface.func_b = WRAPIT(bar);
std:: cout << my_interface.func_a(1,1) << std::endl;
std:: cout << my_interface.func_b('a','b', 1) << std::endl;
return 0;
}
see http://rextester.com/ZZD18334
you may try something like that (Ugly, but works)
#include <iostream>
#include <functional>
struct wrapper_ctx
{
wrapper_ctx ()
{
std::cout << "Before" << std::endl;
}
~wrapper_ctx ()
{
std::cout << "after" << std::endl;
}
};
template <typename F, typename... Args>
auto executor (F&& f, Args&&... args) -> typename std::result_of<F(Args...)>::type
{
wrapper_ctx ctx;
return std::forward<F>(f)( std::forward<Args>(args)...);
}
template <typename F>
class wrapper_helper;
template<typename Ret, typename... Args>
class wrapper_helper <std::function<Ret(Args...)>>
{
std::function<Ret(Args...)> m_f;
public:
wrapper_helper( std::function<Ret(Args...)> f )
: m_f(f) {}
Ret operator()(Args... args) const
{
return executor (m_f, args...);
}
};
template <typename T>
wrapper_helper<T> wrapper (T f)
{
return wrapper_helper <T>(f);
}
int sum(int x, int y)
{
return x + y;
}
int main (int argc, char* argv [])
{
std::function<int(int, int)> f = sum;
auto w = wrapper (f);
std::cout << "Executing the wrapper" << std::endl;
int z = w(3, 4);
std::cout << "z = " << z << std::endl;
}
you probably need something like
template <typename F>
class Wrapper {
public:
Wrapper(F *func) : function(func) {}
operator F* () { return function; }
F *function;
};
Which you can use like void (*funcPtr)(int) = Wrapper<void(int)>(&someFunction);
I think that will be the concise way to do what you want:
template <typename F>
F* wrapper(F* pFunc)
{
return pFunc;
}
and use it like this:
my_interface.func_a = wrapper(foo);
my_interface.func_a(1, 3);
You may try this
template <class R, class... Args>
struct wrap
{
using funct_type = R(*)(Args...);
funct_type func;
wrap(funct_type f): func(f) {};
R operator()(Args&&... args)
{
//before code block
std::cout << "before calling\n";
R ret=func(std::forward<Args>(args)...);
//after code block
std::cout << "After calling\n";
}
};
use like this for example:
int somefunc(double &f, int x);
auto wrapped_somefunc=wrap{somefunc};
double f=1.0;
int x = 2;
auto result=wrapped_somefunc(f,x);
This one is for c++17 and newer uses auto template parameters:
template <auto func, class... Args>
auto wrap_func(Args... args)
{
std::cout << "before calling wrapped func\n";
auto ret = func(args...);
std::cout << "after calling wrapped func\n";
return ret;
}
use for example:
int some_func(int a, int b);
auto ret = wrap_func<some_func>(2, 3);

iterating over variadic template's type parameters

I have a function template like this:
template <class ...A>
do_something()
{
// i'd like to do something to each A::var, where var has static storage
}
I can't use Boost.MPL. Can you please show how to do this without recursion?
EDIT: These days (c++17), I'd do it like this:
template <class ...A>
do_something()
{
((std::cout << A::var << std::endl), ...);
};
What Xeo said. To create a context for pack expansion I used the argument list of a function that does nothing (dummy):
#include <iostream>
#include <initializer_list>
template<class...A>
void dummy(A&&...)
{
}
template <class ...A>
void do_something()
{
dummy( (A::var = 1)... ); // set each var to 1
// alternatively, we can use a lambda:
[](...){ }((A::var = 1)...);
// or std::initializer list, with guaranteed left-to-right
// order of evaluation and associated side effects
auto list = {(A::var = 1)...};
}
struct S1 { static int var; }; int S1::var = 0;
struct S2 { static int var; }; int S2::var = 0;
struct S3 { static int var; }; int S3::var = 0;
int main()
{
do_something<S1,S2,S3>();
std::cout << S1::var << S2::var << S3::var;
}
This program prints 111.
As an example, suppose you want to display each A::var. I see three ways to acomplish this as the code below illustrates.
Regarding option 2, notice that the order in which the elements are processed is not specified by the standard.
#include <iostream>
#include <initializer_list>
template <int i>
struct Int {
static const int var = i;
};
template <typename T>
void do_something(std::initializer_list<T> list) {
for (auto i : list)
std::cout << i << std::endl;
}
template <class... A>
void expand(A&&...) {
}
template <class... A>
void do_something() {
// 1st option:
do_something({ A::var... });
// 2nd option:
expand((std::cout << A::var << std::endl)...);
// 3rd option:
{
int x[] = { (std::cout << A::var << std::endl, 0)... };
(void) x;
}
}
int main() {
do_something<Int<1>, Int<2>, Int<3>>();
}
The answers above work -- here I explore a bit more on using a lambda for complex use cases.
Lambda 101:
[ capture ]( params ){ code }( args to call "in-place" );
If you want to expand a lambda with a variadic template, it won't work as mentioned above when the parameters is of a non-trivial type:
error: cannot pass object of non-trivial type 'Foo' through variadic method; call will abort at runtime.
The way to go is to move the code from the lambda's args to code:
template <class ...A>
do_something() {
Foo foo;
[&](auto&& ...var){
(foo.DoSomething(var), ...);
}(A::var...);
}