Boost.Fusion Functional: Calling functions with default arguments - c++

Is it possible to use boost::fusion::invoke function to call a function that has default arguments without specifying those?
Example:
void foo(int x, int y = 1, int z = 2)
{
std::cout << "The sum is: " << (x + y + z) << std::endl;
}
...
// This should call foo(0). It doesn't work because the type of foo is void (*) (int, int, int).
boost::fusion::invoke(foo, boost::fusion::vector<int>(0));
// Works
boost::fusion::invoke(foo, boost::fusion::vector<int, int, int>(0, 1, 2));
I am writing a wrapper for bindings to a scripting language and default arguments would greatly improve the intuitive feel for the users of the wrapper. I am afraid though that the standard has not covered this case.
A side note:
I know one could work around it using functors:
struct foo {
void operator() (int x, int y = 1, int z = 2) { /* ... */ }
};
// Works because the functor adds an indirection
boost::fusion::invoke(foo(), boost::fusion::vector<int>(0));
This is however not an option as I don't want to force the users to create functors just to specify default arguments.

You can use bind (more info):
boost::fusion::invoke(boost::bind(foo, _1, 1, 2), boost::fusion::vector<int>(0));

Related

Lack of type information in structured bindings

I just learned about structured bindings in C++, but one thing I don't like about
auto [x, y] = some_func();
is that auto is hiding the types of x and y. I have to look up some_func's declaration to know the types of x and y. Alternatively, I could write
T1 x;
T2 y;
std::tie(x, y) = some_func();
but this only works, if x and y are default constructible and not const. Is there a way to write
const auto [x, y] = some_func();
for non-default-constructible types of x and y in a way that makes the types of x and y visible? The compiler should preferably complain when I declare x and y as something incompatible with some_func's return types, i.e. not const auto /* T1, T2 */ [x, y] = some_func();.
Clarification. Since the comments below my question seem to revolve around whether or not to use &, and some previous answers misunderstood my question as "which syntax to use to extract the returned pair's data type", I think I need to clarify my question.
Assume we have our code distributed in multiple files
//
// API.cpp
//
#include <utility>
class Foo {
public:
Foo () {}
};
Foo foo;
class Bar {
private:
Bar () {}
public:
static Bar create () { return Bar(); }
};
Bar bar = Bar::create();
std::pair<int, bool> get_values () {
return std::make_pair(73, true);
}
std::pair<Foo&, Bar&> get_objects () {
return std::pair<Foo&, Bar&>(foo, bar);
}
//
// Program.cpp
//
int main (int, char**) {
const auto [x, y] = get_values();
const auto& [foo, bar] = get_objects();
/* Do stuff with x, y, foo and bar */
return 0;
}
At the time of writing this code the declarations of get_values and get_objects are fresh in my mind, so I know their return types. But when looking at Program.cpp one week later I barely remember the code in main let alone the data types of its variables or the return types of get_values and get_objects, so I need to open API.cpp and find get_values and get_objects to know their return types.
My question is whether there is a syntax to write the data types of the variables x, y, foo and bar in main into the structured binding? Preferably in a manner that allows the compiler to correct me, if I make mistakes, so no comments. Something along the lines of
int main (int, char**) {
// Pseudo-Code
[const int x, const bool y] = get_values();
[const Foo& foo, const Bar& bar] = get_objects();
/* Do stuff with x, y, foo and bar */
return 0;
}
There is no mechanism to state the types of the "variables" in a structured binding declaration. If you want the type names to be visible, you have to forgo the convenience of structured binding declarations.
This is important because of how structured binding works. x and y aren't really variables per-se. They're stand-ins for accessing the components of the object that the structured binding statement stored. They're components of the object that was captured by the declaration. There is only one actual variable: the unnamed variable that is auto-deduced. The names you declare are just components of that object.
Understanding this, now consider this statement: int i = expr; This code works so long as expr is something that can be converted to an int.
If you could put typenames in structured binding declarations, people would have the same expectation. They would expect that if a function returns a tuple<float, int>, they could capture this in an auto [int x, int y]. But they can't, because the object being stored is a tuple<float, int>, and its first member is a float. The compiler would have to invent some new object that contains two ints and do a conversion.
But that's dangerous, particularly when dealing with return values that contain references. You can theoretically turn a tuple<float&, int> into a tuple<int, int>. But it wouldn't have the same meaning, since you cannot modify the object being referenced.
But again, users expect variable declarations to be able to do such conversions. Users rely on it all the time. Taking that power away would serve only to create confusion in the feature.
So the feature doesn't do it.
If you want to preserve structured binding and possible optimisations which comes with it, easiest way would be to put a comment denoting types. Obviously it would be bad if return types were to change: comment would become misleading. When writing types manually this would lead to a compile-time error.
To mimic this behavior, you can force a compile-time error manually:
#include <type_traits>
auto [x, y] = some_func();
static_assert(std::is_same_v<decltype(x), const my_type>);
static_assert(std::is_same_v<decltype(y), some_other__type>);
It will show type information, force a compile-time error if type would ever happens to be not what you expect and even prevent undesired conversions from happening. No more accidentally assigning long to int.
Alternatively: use IDE which can display local variables and their type.
You may do this:
#include <iostream>
#include <tuple>
auto func( )
{
int x = 5;
double y = 5.5;
std::cout << "Executing the func..." << '\n';
return std::make_tuple<int, double>( std::move( x ), std::move( y ) );
}
int main()
{
const auto returnVal = func( );
const int& x = std::get<0>( returnVal );
// const unsigned int& x = std::get<0>( returnVal ); // replace this with the upper one and
// it will provoke a compile-time error
const double& y = std::get<1>( returnVal );
// const char& y = std::get<1>( returnVal ); // replace this with the upper one and
// it will provoke a compile-time error
static_assert( std::is_same_v< decltype( x ), decltype( std::get<0>( returnVal ) ) > &&
std::is_same_v< decltype( y ), decltype( std::get<1>( returnVal ) ) >, "Wrong types used" );
std::cout << x << " " << y << '\n';
return 0;
}
As you can see, this can be a replacement for structured bindings. x and y are references to the returned value. And you do explicitly see their types when reading the source code. And in case you declare them with wrong types then the compiler will complain (e.g. const char& y instead of const double& y ).

std::bind won't accept an std::cref of a bind-placeholder - why?

I try to pass a method as a parameter function, which itself takes a parameter, by using std::cref, but somehow I cannot get it right. What is wrong?
struct node
{
void get(int &i){
i = x;
}
int x, z;
void foo(std::function<void(int&)>t){
t(z);
}
void bar(){
x = 7;
z = 10;
foo(std::bind(&node::get, this, std::cref(_1)));
cout<< "z:" << z << std::endl; //Here is expected that z is changed to 7
}
};
std::bind can only process placeholders directly as parameters: std::bind(…, _1, …).
std::cref(_1) wraps the placeholder in a std::reference_wrapper. bind doesn't recognize it as a placeholder anymore, and tries to pass it directly to the bound function, as it would do with any other non-placeholder parameter.
To work around this and other limitations of bind, use a lambda:
foo([this](int &x){return get(std::ref(x));});
I've replaced cref with ref here, because get() expects a non-const reference. You can't use cref here, with or without the lambda. (Note that std::ref(x) is equivalent to x here, and is used instead of x for demonstration purposes only.)

Hold a collection of member function pointers and decorated member function pointers

As a part of a much larger project, one of my objects (Thing in MWE) has a set of filters (filterStrong, filterWeak) defined on it. The goal is to use all the implemented filters in complexFilteringProcedure, where the user could chose the filtering rule through a parameter, and the function itself would depend on the success of the filtering rule chosen. The function complexFilteringProcedure would act on an object of type Thing, and call one of its private methods (filtering rules) depending on the parameter.
I implemented this by holding a vector of all possible filters in filteringOptions and implementing a single public filtering interface, filterUsingRule. Ideally, this would allow me to later on add new filtering rules to the project as I need them, and only modify the setFilteringFunction where the filter list is initialized.
Now, I started writing a new set of filtering rules, and realized all of them could be obtained by decorating the current filtering rules all in the same manner (softenFilter; please do correct me if "decorating" is the wrong expression here). I remembered reading into std::bind recently and taught, great. I would also like to add all the decorated filtering rules in my list of filteringOptions, that is, every original filter decorated with softenFilter.
Reading up a little bit more on std::bind, I think the possible reasons for my problems are twofold:
the return type of std::bind is a templated mess, and definitely not Thing::filteringFunction
I might be binding the this referring to the calling object when defining softStrong and softWeak
But, I am stuck further than that, not sure how to look for a solution to my specific problem. My main question are: Can this functionality be achieved? (functionality of filterUsingRule) and further, Can this functionality be achieved elegantly? (I know I could always define a set of functions bool softStrong(int param) { return softenFilter(filterStrong, param); } that manually bind the filters to the decorator, but I was hoping that std::bind or some new C++ magic would help with that).
The MWE recreating what I have successfully done and what I would like to achieve is as follows:
#include <iostream>
#include <vector>
#include <functional>
class Thing{
private:
int basicFilter;
typedef bool (Thing::*filteringFunction)(int);
static std::vector<filteringFunction> filteringOptions;
bool filterStrong(int parameter) {return parameter > basicFilter*2;}
bool filterWeak(int parameter) {return parameter > basicFilter;}
bool softenFilter(filteringFunction f, int parameter){
if (!((this->*(f))(parameter)))
return (this->*(f))(parameter+2);
return true;
}
void setFilteringFunctions(void){
Thing::filteringOptions.emplace_back(&Thing::filterStrong);
Thing::filteringOptions.emplace_back(&Thing::filterWeak);
auto softStrong = std::bind(&Thing::softenFilter,
&Thing::filterStrong,
std::placeholders::_1); // ok
auto softWeak = std::bind(&Thing::softenFilter,
&Thing::filterWeak,
std::placeholders::_1); // ok
filteringOptions.emplace_back(&softStrong); // how?
filteringOptions.emplace_back(softWeak); // how?
}
public:
Thing(int basicFilter) : basicFilter(basicFilter){
if (Thing::filteringOptions.empty())
setFilteringFunctions();
}
bool filterUsingRule(int parameter, int rule = 0){
return ((int)Thing::filteringOptions.size() > rule) &&
(this->*(Thing::filteringOptions[rule]))(parameter);
}
};
std::vector <Thing::filteringFunction> Thing::filteringOptions(0);
void complexFilteringProcedure(Thing &aThing, int parameter, int rule){
// do a lot of things
if (aThing.filterUsingRule(parameter, rule))
std::cout << "Filtering with " << rule << "successful" << std::endl;
else
std::cout << "Filtering with " << rule << "failed" << std::endl;
// and some more things
}
int main(void){
Thing myThing(5), otherThing(10);
complexFilteringProcedure(myThing, 7, 0); // uses strong rule
complexFilteringProcedure(otherThing, 7, 1); // uses weak rule
complexFilteringProcedure(myThing, 7, 2); // how to do this correctly?
complexFilteringProcedure(otherThing, 7, 3); // or this?
}
You might use std::function
using filteringFunction = std::function<bool (Thing&, int)>;
and then
void setFilteringFunctions()
{
Thing::filteringOptions.emplace_back(&Thing::filterStrong);
Thing::filteringOptions.emplace_back(&Thing::filterWeak);
auto softStrong = std::bind(&Thing::softenFilter,
std::placeholders::_1,
&Thing::filterStrong,
std::placeholders::_2
);
auto softWeak = std::bind(&Thing::softenFilter,
std::placeholders::_1,
&Thing::filterWeak,
std::placeholders::_2);
Thing::filteringOptions.emplace_back(&softStrong);
Thing::filteringOptions.emplace_back(&softWeak);
// or
Thing::filteringOptions.emplace_back([](Thing& instance, int param){
return instance.filterStrong(param + 2) });
}
You'll have to use a specialization of std::function as your vector element type. The key issue is that the object returned by std::bind() is not a bare function pointer. It is rather a Callable -- a function object -- it is some type (exactly what type is unimportant and in fact unspecified) that has an operator() with the appropriate return type which takes the appropriate parameters. This is exactly the role of std::function -- a type which can wrap any Callable of the correct signature in a way that lets you handle it with a known concrete type regardless of the actual type of the Callable.
typedef std::function<bool(int)> filteringFunction;
static std::vector<filteringFunction> filteringOptions;
// now can you store your member function pointers in
// filteringOptions after bind()ing the first parameter
// as you've already done
To satisfy the skeptics, here is the OP's code modified to use this technique.
#include <iostream>
#include <vector>
#include <functional>
class Thing{
private:
int basicFilter;
typedef std::function<bool(int)> filteringFunction;
static std::vector<filteringFunction> filteringOptions;
bool filterStrong(int parameter) {return parameter > basicFilter*2;}
bool filterWeak(int parameter) {return parameter > basicFilter;}
bool softenFilter(filteringFunction f, int parameter){
if (!f(parameter))
return f(parameter + 2);
return true;
}
void setFilteringFunctions(void){
filteringFunction strong = std::bind(&Thing::filterStrong,
this, std::placeholders::_1);
filteringFunction weak = std::bind(&Thing::filterWeak,
this, std::placeholders::_1);
filteringFunction softStrong = std::bind(&Thing::softenFilter,
this, strong, std::placeholders::_1);
filteringFunction softWeak = std::bind(&Thing::softenFilter,
this, weak, std::placeholders::_1);
filteringOptions.emplace_back(softStrong);
filteringOptions.emplace_back(softWeak);
}
public:
Thing(int basicFilter) : basicFilter(basicFilter){
if (Thing::filteringOptions.empty())
setFilteringFunctions();
}
bool filterUsingRule(int parameter, int rule = 0){
return ((int)Thing::filteringOptions.size() > rule) &&
filteringOptions[rule](parameter);
}
};
std::vector <Thing::filteringFunction> Thing::filteringOptions(0);
void complexFilteringProcedure(Thing &aThing, int parameter, int rule){
// do a lot of things
std::cout << "Filtering: " << aThing.filterUsingRule(parameter, rule) << std::endl;
// and some more things
}
int main(void){
Thing myThing(5), otherThing(10);
complexFilteringProcedure(myThing, 7, 0); // uses strong rule
complexFilteringProcedure(otherThing, 7, 1); // uses weak rule
//complexFilteringProcedure(myThing, 7, 2); // how to use soft strong rule?
//complexFilteringProcedure(otherThing, 7, 3); // how to use soft weak rule?
}
typedef std::function<bool(Thing*, int)> filteringFuction;
Now you can use static functions as well as std::bind and lambda or any callable that accepts an int and returns bool.
static bool test(Thing*, int);
static bool decoratee(Thing*, bool , int);
this->filteringOptions.emplace_back([](Thing* sth, int x){return false;});
this->filteringOptions.emplace_back(&Thing::weakFilter);
this->filteringOptions.emplace_back(std::bind(decoratee, _1, false, _2));
this->filteringOptions.emplace_back(&test);
int param;
for(auto& callee:this->filteringOptions)
callee(this,param);

C++: Adding and redefinition of default arguments in real world

There is a possibility to add or redefine default arguments of a function in C++. Let's look at the example:
void foo(int a, int b, int c = -1) {
std::cout << "foo(" << a << ", " << b << ", " << c << ")\n";
}
int main() {
foo(1, 2); // output: foo(1, 2, -1)
// void foo(int a, int b = 0, int c);
// error: does not use default from surrounding scope
void foo(int a, int b, int c = 30);
foo(1, 2); // output: foo(1, 2, 30)
// void foo(int a, int b, int c = 35);
// error: we cannot redefine the argument in the same scope
// has a default argument for c from a previous declaration
void foo(int a, int b = 20, int c);
foo(1); // output: foo(1, 20, 30)
void foo(int a = 10, int b, int c);
foo(); // output: foo(10, 20, 30)
{
// in inner scopes we can completely redefine them
void foo(int a, int b = 4, int c = 8);
foo(2); // output: foo(2, 4, 8)
}
return 0;
}
Online version to play with: http://ideone.com/vdfs3t
These possibilities are regulated by the standard in 8.3.6. More specific details are in 8.3.6/4
For non-template functions, default arguments can be added in later
declarations of a function in the same scope. Declarations in
different scopes have completely distinct sets of default arguments.
That is, declarations in inner scopes do not acquire default arguments
from declarations in outer scopes, and vice versa. In a given function
declaration, each parameter subsequent to a parameter with a default
argument shall have a default argument supplied in this or a previous
declaration or shall be a function parameter pack. A default argument
shall not be redefined by a later declaration (not even to the same
value)
...
To tell the truth I never use this feature when coding in c++. I used similar code snippets several times to surprise my colleagues, but certainly not in the production code. Thus, the question is: Do you know real world examples of the code that use these features with benefits?
If you cannot change some existing code or library and you really cannot be bothered to type the correct argument then changing the default argument for some scope could be a solution.
It seems like the kind of hack that could be useful when working with C++ code generated by some legacy tool. For example, if the generated code has always had hundreds calls into some external library using a default argument but now the default argument is no longer correct.

How can I cleanly specify which arguments I am passing and which remain default?

Asked because of this: Default argument in c++
Say I have a function such as this: void f(int p1=1, int p2=2, int p3=3, int p4=4);
And I want to call it using only some of the arguments - the rest will be the defaults.
Something like this would work:
template<bool P1=true, bool P2=true, bool P3=true, bool P4=true>
void f(int p1=1, int p2=2, int p3=3, int p4=4);
// specialize:
template<>
void f<false, true, false, false>(int p1) {
f(1, p1);
}
template<>
void f<false, true, true, false>(int p1, int p2) {
f(1, p1, p2);
}
// ... and so on.
// Would need a specialization for each combination of arguments
// which is very tedious and error-prone
// Use:
f<false, true, false, false>(5); // passes 5 as p2 argument
But it requires too much code to be practical.
Is there a better way to do this?
Use the Named Parameters Idiom (→ FAQ link).
The Boost.Parameters library (→ link) can also solve this task, but paid for by code verbosity and greatly reduced clarity. It's also deficient in handling constructors. And it requires having the Boost library installed, of course.
Have a look at the Boost.Parameter library.
It implements named paramaters in C++. Example:
#include <boost/parameter/name.hpp>
#include <boost/parameter/preprocessor.hpp>
#include <iostream>
//Define
BOOST_PARAMETER_NAME(p1)
BOOST_PARAMETER_NAME(p2)
BOOST_PARAMETER_NAME(p3)
BOOST_PARAMETER_NAME(p4)
BOOST_PARAMETER_FUNCTION(
(void),
f,
tag,
(optional
(p1, *, 1)
(p2, *, 2)
(p3, *, 3)
(p4, *, 4)))
{
std::cout << "p1: " << p1
<< ", p2: " << p2
<< ", p3: " << p3
<< ", p4: " << p4 << "\n";
}
//Use
int main()
{
//Prints "p1: 1, p2: 5, p3: 3, p4: 4"
f(_p2=5);
}
Although Boost.Parameters is amusing, it suffers (unfortunately) for a number of issues, among which placeholder collision (and having to debug quirky preprocessors/template errors):
BOOST_PARAMETER_NAME(p1)
Will create the _p1 placeholder that you then use later on. If you have two different headers declaring the same placeholder, you get a conflict. Not fun.
There is a much simpler (both conceptually and practically) answer, based on the Builder Pattern somewhat is the Named Parameters Idiom.
Instead of specifying such a function:
void f(int a, int b, int c = 10, int d = 20);
You specify a structure, on which you will override the operator():
the constructor is used to ask for mandatory arguments (not strictly in the Named Parameters Idiom, but nobody said you had to follow it blindly), and default values are set for the optional ones
each optional parameter is given a setter
Generally, it is combined with Chaining which consists in making the setters return a reference to the current object so that the calls can be chained on a single line.
class f {
public:
// Take mandatory arguments, set default values
f(int a, int b): _a(a), _b(b), _c(10), _d(20) {}
// Define setters for optional arguments
// Remember the Chaining idiom
f& c(int v) { _c = v; return *this; }
f& d(int v) { _d = v; return *this; }
// Finally define the invocation function
void operator()() const;
private:
int _a;
int _b;
int _c;
int _d;
}; // class f
The invocation is:
f(/*a=*/1, /*b=*/2).c(3)(); // the last () being to actually invoke the function
I've seen a variant putting the mandatory arguments as parameters to operator(), this avoids keeping the arguments as attributes but the syntax is a bit weirder:
f().c(3)(/*a=*/1, /*b=*/2);
Once the compiler has inlined all the constructor and setters call (which is why they are defined here, while operator() is not), it should result in similarly efficient code compared to the "regular" function invocation.
This isn't really an answer, but...
In C++ Template Metaprogramming by David Abrahams and Aleksey Gurtovoy (published in 2004!) the authors talk about this:
While writing this book, we reconsidered the interface used for named
function parameter support. With a little experimentation we
discovered that it’s possible to provide the ideal syntax by using
keyword objects with overloaded assignment operators:
f(slew = .799, name = "z");
They go on to say:
We’re not going to get into the implementation details of this named
parameter library here; it’s straightforward enough that we suggest
you try implementing it yourself as an exercise.
This was in the context of template metaprogramming and Boost::MPL. I'm not too sure how their "straighforward" implementation would jive with default parameters, but I assume it would be transparent.