Limiting the number of arguments in a variadic function - c++

So I've been working on a function class, and by default, I can do this, and it works:
int main(){
function f("x^2+1");
cout<<f(3)<<endl;
return 0;
}
"assume proper includes and namespaces"
Anyways, I would like to be able to pass in multiple variables, and even state what those variables are, like;
function f("x^2+y^2",x,y); // it doesn't really matter if it's x, 'x', or "x"
cout<<f(3,4)<<endl; // input 3 as x, and 4 as y
I'm fairly certain I could figure something out for the constructor using variadic functions, and even solve properly, but would there be a way to force the operator() arguments to take in exactly 2 values?
I was just looking at variadic functions because they are really the first things I've seen in c++ that can take in multiple arguments, so if it is better to do this some other way, I'm all for it.

You can limit the number of variadic arguments by using a static_assert.
template <typename ... Args>
void operator()(Args&&... args)
{
static_assert(sizeof...(Args) <= 2, "Can deal with at most 2 arguments!");
}
Or you could use an enable_if
template <typename ... Args>
auto operator()(Args&&... args) -> std::enable_if_t<sizeof...(Args) <= 2>
{
}

template<class T>
using double_t=double;
template<class...Ts>
using nfun=std::function<double(double_t<Ts>...)>;
template<class...C>
nfun<C...> func(const char*,C...c);
that will return a n-ary std::function equal to the number of 'variable' arguments to func.
So func("x^2+y",'x','y','z') will return std::function<double(double,double,double)> as an example.

Related

Best way to apply a void function to a parameter pack

I would like to write a function that applies a function to each element of a parameter pack. The functions returns a std::tuple with the results of each invocation.
However, if the applied function returns void, I have to do something else, so I have a different overload for this case. But, almost all the ways I've found to expand the parameter pack do not work with void expressions, so I had to resort to what you see below, which seems a weird trick.
template<typename F, typename ...Args>
requires requires { std::tuple{std::declval<F>(Args)...}; }
auto for_each(F f, Args ...args) {
return std::tuple{f(args)...};
}
template<typename F, typename ...Args>
auto for_each(F f, Args ...args)
[[maybe_unused]] int a[] = {(f(Members), 0)...};
}
Note that I have to declare a unused variable and mark it with the attribute.
Which is the best way to obtain the expected result here?
This trick is the way to go pre-C++17, except that you need an extra , 0 in the array to support zero-length packs.
In C++17 and newer, use a fold expression: (f(args), ...);.
Note that you forgot perfect forwarding. You should be doing F &&f, Args &&... args, and then (f(std::forward<Args>(args)), ...);, and similarly for the first function.
I also question the value of having such a function. I'd understand doing this to a tuple, but if you already have a pack, you can do this manually at the call site.

Execute a function on each element of a list of types that's not in a parameter pack? [duplicate]

I would like to do
template<typename... ArgTypes> void print(ArgTypes... Args)
{
print(Args)...;
}
And have it be equivalent to this quite bulky recursive chain:
template<typename T, typename... ArgTypes> void print(const T& t, ArgTypes... Args)
{
print(t);
print(Args...);
}
followed by explicit single-parameter specializations for every type I'd like to print.
The "problem" with the recursive implementation is that a lot of redundant code is generated, because each recursive step results in a new function of N-1 arguments, whereas the code I'd like to have would only generate code for a single N-arg print function, and have at most N specialized print functions.
C++17 fold expression
(f(args), ...);
If you call something that might return an object with overloaded comma operator use:
((void)f(args), ...);
Pre-C++17 solution
The typical approach here is to use a dumb list-initializer and do the expansion inside it:
{ print(Args)... }
Order of evaluation is guaranteed left-to-right in curly initialisers.
But print returns void so we need to work around that. Let's make it an int then.
{ (print(Args), 0)... }
This won't work as a statement directly, though. We need to give it a type.
using expand_type = int[];
expand_type{ (print(Args), 0)... };
This works as long as there is always one element in the Args pack. Zero-sized arrays are not valid, but we can work around that by making it always have at least one element.
expand_type{ 0, (print(Args), 0)... };
We can make this pattern reusable with a macro.
namespace so {
using expand_type = int[];
}
#define SO_EXPAND_SIDE_EFFECTS(PATTERN) ::so::expand_type{ 0, ((PATTERN), 0)... }
// usage
SO_EXPAND_SIDE_EFFECTS(print(Args));
However, making this reusable requires a bit more attention to some details. We don't want overloaded comma operators to be used here. Comma cannot be overloaded with one of the arguments void, so let's take advantage of that.
#define SO_EXPAND_SIDE_EFFECTS(PATTERN) \
::so::expand_type{ 0, ((PATTERN), void(), 0)... }
If you are paranoid afraid of the compiler allocating large arrays of zeros for naught, you can use some other type that can be list-initialised like that but stores nothing.
namespace so {
struct expand_type {
template <typename... T>
expand_type(T&&...) {}
};
}
C++17 fold expression:
(f(args), ...);
Keep simple things simple ;-)
If you call something that might return an object with overloaded comma operator use:
((void)f(args), ...);
You can use even more simple and readable approach
template<typename... ArgTypes> void print(ArgTypes... Args)
{
for (const auto& arg : {Args...})
{
print(arg);
}
}
I have played with both variants on compile explorer and both gcc and clang with O3 or O2 produce exactly the same code but my variant is obviously cleaner.

C++ Lambdas with Ellipses in the Parameter List

I'm working on a library which uses lambdas for delineating the scopes of expression terms. Because the library has to hand out unique integer numbers to identify each variable, it is ideal if the library, not the user, constructs the variables and the user code receives them as lambda arguments.
(In other words I am implementing a C++ analog of "call\fresh" from miniKanren.)
Since the user may want to introduce any number from zero to many fresh variables at a particular scope, I want the user to be able to pass lambdas with differing numbers of arguments to the library. However, I'm not aware of any (simple) way (in C++14) to deduce the number of parameters to an arbitrary lambda object.
An idea occurred to me why not pass a fixed number (say, 10) of variable-id arguments to the lambda, and have the user code use ellipses in the lambda to ignore the ones not needed? Something like this:
auto no_args = call_fresh([](...) { return success(); });
auto one_arg = call_fresh([](var A, ...) { return A == 1; });
auto two_args = call_fresh([](var A, var B, ...) { return A == 1 && B == 2; });
Compiler explorer seems to accept ellipses in lambda parameter lists, at least with gcc.
It would be called something like this (note how the code always passes 10 variable id's no matter whether "f" names only one, two, or none of them):
template <typename F>
auto call_fresh(F f)
{
return [f](StateCounter sc) {
return f(sc+0,sc+1,sc+2,sc+3,sc+4,
sc+5,sc+6,sc+7,sc+8,sc+9);
};
}
Granted it's a feature I was surprised exists, is there any reason not to use lambdas with ellipses?
However, I'm not aware of any (simple) way (in C++14) to deduce the number of parameters to an arbitrary lambda object.
It seems to me that you're looking for sizeof...() over a variadic auto list of paramenters
#include <iostream>
int main ()
{
auto l = [](auto ... as) { return sizeof...(as); };
std::cout << l(1, 2L, 3.0, 4.0f, "5") << std::endl; // print 5
}
Your lambdas are essentially C-style variadic functions. There's nothing wrong with using them, and if you don't want to access the values (which is somewhat ugly), that is fine.
However, the underlying problem that it seems like you actually want to solve is to let your library find the number of arguments (or arity) of a function/lambda/..., which you can do with template metaprogramming - no need for your users to work around that issue.
Disclosure: There is an implementation of this in a library that I also work on, here.
Here is a simple example:
template <typename Callable>
struct function_arity : public function_arity<decltype(&Callable::operator())>
{};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_arity<ReturnType(ClassType::*)(Args...) const>
{
constexpr static size_t arity = sizeof...(Args);
};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_arity<ReturnType(ClassType::*)(Args...)>
{
constexpr static size_t arity = sizeof...(Args);
};
The compiler will automatically deduce the argument types for you, and sizeof... will get you the number of arguments that you need.
Then, you can use function_arity<decltype(lambda)>::arity to get the number of arguments of your lambda. The last version deals with mutable lambdas, where the call operator is non-constant. You may also want to extend this to work properly with noexcept, or you will run into errors like this libc++ bug.
Unfortunately, this will not work with overloaded or templated operator() (e.g. if you use auto-type parameters in your lambda). If you also want to support functions instead of lambdas, additional specializations may be necessary.

Call a function with parameter from a pack of functors in variadic template

I had a (lambda) function and a lot of functors passed as variadic argument pack into a third function. The signature looks like
template<typename F, typename... G>
ret_t call(F&& func, G&&... getters);
and F shall have as many as argument as the number of getters given.
Now I need to call func with the return value of getter called against a hard-coded (constexpr) constant determined otherwise. So untemplated code might look like
{
return func(getters_1(0), getters_2(0), getters_3(0) /* , ... */);
}
Of course I want to automate the process with template metaprogramming.
I want to avoid a temporary array or whatever intermediate container. (This is not aimed to that generic, I know the return type of getters.) I want it to be passed to the function as directly as possible so as to enable optimization and avoid waste of memory.
I could have wrapped F with many levels of closure of lambda, each wraps one parameter to it, and hope the best from compiler, but anyways I'm asking for better and clearer ways to do it.
If I understood you correctly you want something like this:
template<typename F, typename... G>
ret_t call(F&& func, G&&... getters) {
return std::forward<F>(func)(std::forward<G>(getters)(0)...);
}

Expanding an STL container into a variadic template

To keep things generic and straightforward, say that I have a std::vector of integers, such as:
std::vector<int> v;
Now, what I am wondering is, is it possible to take n (where n is a constant known at compile time) values from v and pass them to an arbitrary function? I know that this is doable with variadic templates:
template<typename... T>
void pass(void (*func)(int, int, int), T... t) {
func(t...);
}
And then we hope 'pass' is called with exactly 3 integers. The details don't matter so much. What I am wondering is, is the following somehow doable:
void pass(void (*func)(int, int, int), std::vector<int> &t) {
auto iter = t.begin();
func((*iter++)...);
}
Where ... is being used like a variadic template? Essentially, I'm asking if I can
Expand a std::vector or other STL container into a variadic template with n elements
And/or in-order pass these values directly to a function being called
Is this possible with C++11? Noting that I need this to work on MSVC v120/VS2013.
It's definitely possible, but you cannot determine the safety of doing it at compile time. This is, as WhozCraig says, because the vector lacks a compile-time size.
I'm still trying to earn my template meta programming wings, so I may have done things a little unusually. But the core idea here is to have a function template recursively invoke itself with the next item in the vector until it has built up a parameter pack with the desired parameters. Once it has that, it's easy to pass it to the function in question.
The implementation of the core here is in apply_first_n, which accepts a target std::function<R(Ps...)>, and a vector, and a parameter pack of Ts.... When Ts... is shorter than Ps... it builds up the pack; once it's the same size, it passes it to the function.
template <typename R, typename... Ps, typename... Ts>
typename std::enable_if<sizeof...(Ps) == sizeof...(Ts), R>::type
apply_first_n(std::function<R(Ps...)> f, const std::vector<int> &v, Ts&&... ts)
{
if (sizeof...(Ts) > v.size())
throw std::out_of_range("vector too small for function");
return f(std::forward<Ts>(ts)...);
}
template <typename R, typename... Ps, typename... Ts>
typename std::enable_if<sizeof...(Ps) != sizeof...(Ts), R>::type
apply_first_n(std::function<R(Ps...)> f, const std::vector<int> &v, Ts&&... ts)
{
const int index = sizeof...(Ps) - sizeof...(Ts) - 1;
static_assert(index >= 0, "incompatible function parameters");
return apply_first_n(f, v, *(std::begin(v) + index), std::forward<Ts>(ts)...);
}
You call this with, e.g., apply_first_n(std::function<int(int, int)>(f), v);. In the live example, make_fn just makes the conversion to std::function easier, and ProcessInts is a convenient testing function.
I'd love to figure out how to avoid the use of std::function, and to repair any other gross inefficiencies that exist. But I'd say this is proof that it's possible.
For reference, I took the above approach further, handling set, vector, tuple, and initializer_list, as well as others that match the right interfaces. Removing std::function seemed to require the func_info traits class, as well as several overloads. So while this extended live example is definitely more general, I'm not sure I'd call it better.