What is the correct way to call this method? - c++11

I'm trying to understand placeholders but i can't call this method. I have an implicit parameters Dummy{}, float and LastDummy{}. When i call function i skip these parameters. Also my call doesn't work.
struct AnotherDummy {};
struct YetAnotherDummy {};
struct LastDummy {};
class X { public:
void foo(std::string one, Dummy two, int three, AnotherDummy four,
float five, YetAnotherDummy six, double seven, int eight, LastDummy nine)
{
}
};
int main()
{
using namespace std::placeholders;
auto functor = std::bind(&X::foo, _6, _3, Dummy{}, _5, _1, 5.0f, _4, _2, _7, LastDummy{});
X obj;
functor(&obj, YetAnotherDummy{}, 1, 2.3f, 'x', AnotherDummy{}, Dummy{}, 2.3);
return 0;
}

For non-static member functions the object to call the function on (what becomes the this pointer inside the member function) is passed as a hidden first argument.
So the major problem with the usage of functor is that the X object obj should be the first argument to the function, i.e. placeholder _1. The remaining arguments starts at placeholder _2.
So you need to do e.g.
auto functor = std::bind(&X::foo, _1, _7, _4, Dummy{}, _6, _2, 5.0f, _5, _3, _8, LastDummy{});
Note that _1 is not the first argument to the function, and that the remaining placeholders have been increased by 1.

Related

Using coeffRef with const CwiseUnaryView - Failing when multiplying two CWiseUnaryViews

I'm having some trouble when using coeffRef() with a CWiseUnaryView function, but only when the function is declared as const
Reproducible example:
#include <Eigen/Core>
struct dummy_Op {
EIGEN_EMPTY_STRUCT_CTOR(dummy_Op)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE const double&
operator()(const double &v) const { return v; }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE double&
operator()(double &v) const { return v; }
};
void foo(Eigen::MatrixXd &out)
{
//Compiles
Eigen::CwiseUnaryView<dummy_Op, Eigen::MatrixXd> view(out);
view.coeffRef(0,0);
//Doesn't Compile
const Eigen::CwiseUnaryView<dummy_Op, Eigen::MatrixXd> const_view(out);
const_view.coeffRef(0,0);
}
Returns:
<source>: In function 'void foo(Eigen::MatrixXd&)':
<source>:21:28: error: passing 'const Eigen::CwiseUnaryView<dummy_Op,
Eigen::Matrix<double, -1, -1> >' as 'this' argument discards qualifiers
[-fpermissive]
const_view.coeffRef(0,0);
^
In file included from /opt/compiler-explorer/libs/eigen/v3.3.4/Eigen/Core:413,
from <source>:1:
/opt/compiler-explorer/libs/eigen/v3.3.4/Eigen/src/Core/DenseCoeffsBase.h:340:33: note:
in call to 'Eigen::DenseCoeffsBase<Derived, 1>::Scalar&
Eigen::DenseCoeffsBase<Derived, 1>::coeffRef(Eigen::Index, Eigen::Index)
[with Derived = Eigen::CwiseUnaryView<dummy_Op, Eigen::Matrix<double,
-1, -1> >; Eigen::DenseCoeffsBase<Derived, 1>::Scalar = double; Eigen::Index = long int]'
EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col)
^~~~~~~~
Compiler returned: 1
Compiler explorer: https://godbolt.org/z/kPHPuC
The side-effect of this, is that the multiplication of two (non-const) CWiseUnaryViews also fails, see example here: https://godbolt.org/z/JYQb3d
The bottom line is that you're calling a non-const method of a constant instance. The (first) coeffRef that is being called is the one (and only) in DenseCoeffsBase.h (DenseCoeffsBase<Derived, WriteAccessors>), which is not const qualified. The DenseCoeffsBase<Derived, ReadOnlyAccessors> class does not have a coeffRef method. You can get around this error (and get a warning) if you enable the -fpermissive compiler flag.
In the dense case, you probably want to use the operator()(Index, Index) method anyway, which does have a const qualified version. I just noticed the documentation explicitly says to use that method anyway, even for the non-const version. This is obviously not going to return a const reference, but at least in your example as a double, it shouldn't matter too much.
CwiseUnaryView is intended to be used for L-value like expression, e.g.,
MatrixXcd A;
A.real() = something; // `A.real()` is writable
If you want to apply an element-wise functor and use it as an R-value, you should use CwiseUnaryOp instead:
void foo(Eigen::MatrixXd &out)
{
Eigen::CwiseUnaryOp<dummy_Op, Eigen::MatrixXd> view1(out);
// shorter:
auto view2 = out.unaryExpr(dummy_Op());
Eigen::MatrixXd result = view1 * view2;
// or directly write: out.unaryExpr(dummy_Op()) * out.unaryExpr(dummy_Op());
}

C++11: Variadic template deduction logic

I have the following construct:
template <class... Args>
class some_class
{
public:
some_class() = default;
some_class(Args...) = delete;
~some_class() = default;
};
template<>
class some_class<void>
{
public:
some_class() = default;
~some_class() = default;
};
The reason for this is that I just want to allow the users to create objects using the default constructor, so for example:
some_class<int,float> b;
should work but
some_class<int,float> c(1,3.4);
should give me a compilation error.
At some point in time I also needed to create templates based on void hence, the specialization for void:
some_class<void> a;
But by mistake I have typed:
some_class<> d;
And suddenly my code stopped compiling and it gave me the error:
some_class<Args>::some_class(Args ...) [with Args = {}]’ cannot be
overloaded
some_class(Args...) = delete;
So here comes the question: I feel that I am wrong that I assume that some_class<> should be deduced to the void specialization... I just don't know why. Can please someone explain why some_class<> (ie: empty argument list) is different from some_class<void>? (A few lines from the standard will do :) )
https://ideone.com/o6u0D6
void is a type like any other (an incomplete type, to be precise). This means it can be used as a template argument for type template parameters normally. Taking your class template, these are all perfectly valid, and distinct, instantiations:
some_class<void>
some_class<void, void>
some_class<void, void, void>
some_class<void, char, void>
In the first case, the parameter pack Args has one element: void. In the second case, it has two elements: void and void. And so on.
This is quite different from the case some_class<>, in which case the parameter pack has zero elements. You can easily demonstrate this using sizeof...:
template <class... Pack>
struct Sizer
{
static constexpr size_t size = sizeof...(Pack);
};
int main()
{
std::cout << Sizer<>::size << ' ' << Sizer<void>::size << ' ' << Sizer<void, void>::size << std::endl;
}
This will output:
0 1 2
[Live example]
I can't really think of a relevant part of the standard to quote. Perhaps this (C++11 [temp.variadic] 14.5.3/1):
A template parameter pack is a template parameter that accepts zero or more template arguments. [ Example:
template<class ... Types> struct Tuple { };
Tuple<> t0; // Types contains no arguments
Tuple<int> t1; // Types contains one argument: int
Tuple<int, float> t2; // Types contains two arguments: int and float
Tuple<0> error; // error: 0 is not a type
—end example ]

Additional move constructor in pass by value function

I have a simple struct, that has all constructors defined.
It has an int variable, each constructor and assign operator prints address of *this, current value of int and a new value of int.
Move and copy assign operators and constructors also print adress of passed value.
#include <iostream>
struct X
{
int val;
void out(const std::string& s, int nv, const X* from = nullptr)
{
std::cout<<this<<"->"<<s<<": "<<val<<" ("<<nv<<")";
if (from)
std::cout<<", from: ["<<from<<"]";
std::cout<<"\n";
}
X(){out("simple ctor X()",0); val = 0;}
X(int v){out("int ctor X(int)", v);val = v; }
X(const X& x){out("copy ctor X(X&)", x.val, &x);val = x.val; };
X&operator = (const X& x){out("copy X::operator=()", x.val, &x); val = x.val; return *this;}
~X(){out("dtor ~X", 0);}
X&operator = (X&& x){out("move X::operator(&&)", x.val, &x); val = x.val; return *this;}
X(X&& x){out("move ctor X(&&x)", x.val, &x);val = x.val;}
};
X copy(X a){return a;}
int main(int argc, const char * argv[]) {
X loc{4};
X loc2;
std::cout<<"before copy\n";
loc2 = copy(loc);
std::cout<<"copy finish\n";
}
output:
0xffdf7278->int ctor X(int): 134523184 (4)
0xffdf727c->simple ctor X(): 134514433 (0)
before copy
0xffdf7280->copy ctor X(X&): 1433459488 (4), from: [0xffdf7278]
0xffdf7284->move ctor X(&&x): 1433437824 (4), from: [0xffdf7280]
0xffdf727c->move X::operator(&&): 0 (4), from: [0xffdf7284]
0xffdf7284->dtor ~X: 4 (0)
0xffdf7280->dtor ~X: 4 (0)
copy finish
0xffdf727c->dtor ~X: 4 (0)
0xffdf7278->dtor ~X: 4 (0)
What's the purpose of creating an additional object with (in this example) address 0xffdf7284?
If you look at the copy elision rules from cppreference.com, you can notice that there are two case where the compilers are required to omit the copy- and move- constructors of class objects even if copy/move constructor and the destructor have observable side-effects (which yours do, due to the printouts). The first is clearly irrelevant to this case. The second is
In a function call, if the operand of a return statement is a prvalue and the return type of the function is the same as the type of that prvalue.
With the example given of:
T f() { return T{}; }
T x = f();
This seems more relevant, however, note that in your case, the operand of the return statement is not a prvalue. So in this case, no mandatory elision applies.
The set of steps, when callingloc2 = copy(loc);, is as follows:
a is copy-constructed from loc.
The return value of the function is move-constructed from a.
loc2 is move-assigned from the return value.
Logically, a person could look at the code and deduce that fewer operations need to be done (in particular, when looking at copy, it's obvious that, logically, an assignment from loc to loc2 is enough), but the compiler doesn't know that the purpose of your code isn't to generate the side effects (the printouts), and it is not breaking any rules here.

C++ 11: What type of callable should I use when using sorted vector to simulate map

Scott Meyer's Effective STL showed an example of using sorted vector of pair<key, value> to simulate a map or multimap. In order to sort the vector and later look up the elements in the vector, he has to create a functor DataCompare where there are 3 overloaded function operator(): one that takes two pair object for sorting; two that take a pair and a key because in algorithms like lower_bound, equal_range, we don't know the order in which the key object and the pair object are passed to the custom comparison functor:
typedef pair<string, int> Data; // type held in the "map"
class DataCompare { // class for comparison
public:
bool operator()(const Data& lhs, const Data& rhs) const // comparison func for sorting
{
return keyLess(lhs.first, rhs.first);
}
bool operator()(const Data& Ihs, const Data::first_type& k) const // comparison func for lookups
{ //(form 1)
return keyLess(lhs.first, k);
}
bool operator()(const Data::first_type& k, const Data& rhs) const // comparison func for lookups
{ // (form 2)
return keyLessfk, rhs.first);
}
....
Now that we have C++11, we have lambda and std::bind and std::function to replace functors. But how do I use lambda or std::bind or std::function to deal with the uncertainty of the order the arguments are passed in (lookup) algorithms like lower_bound, upper_bound and equal_range?
In http://www.cplusplus.com/reference/algorithm/lower_bound/, the description for comp seems to suggest I can create a lambda whose first parameter can be the pair and the second parameter can be of the same type as key. However, inside the implementation of lower_bound, it can switch the order in calling the lambda. In g++ (my version is 4.8.4), I got the following error:
... else if (__comp(__val, *__middle))
...
no known conversion for argument 1 from ‘const std::basic_string’ to ‘const ms2dict& {aka const std::pair< std::basic_string< char>, std::basic_string< char> >&}’
Here the else if (__comp(__val, *__middle)) is using the lambda but passing the arguments in reverse order. Is there a way to create a universal callable object that deal with this problem?

Function taking lambda expression

For practicing purposes I wanted to create a function similar to std::transform():
template<class Tin, class Tout>
std::vector<Tout> map( const std::vector<Tin>& in,
const std::function<Tout(const Tin&)>& mapper ) {
std::vector<Tout> ret;
for( auto elem : in ) {
ret.push_back( mapper( in ) );
}
return ret;
}
and I intended it to use it as follows:
std::vector<Bar> bars /* = ... */;
std::vector<Foo> foos = map( bars, []( const Bar& bar ) { return bar.to_foo(); } );
However, I get undefined references for the function call. What is the correct signature for my map() function?
*Update: * Here's the actual error message (Bar = std::string, Foo = IPv6 (own class))
config.cc:98:61: error: no matching function for call to ‘map(const std::vector<IPv6>&, InterfaceConfig::set_ip6(const std::vector<IPv6>&)::<lambda(const IPv6&)>)’
config.cc:98:61: note: candidate is:
utils.h:38:31: note: template<class Tin, class Tout> std::vector<Tout> utils::map(const std::vector<Tin>&, const std::function<Tout(const Tin&)>&)
And here's the call:
std::vector strings = utils::map( ips,
[]( const IPv6& ip ) { return ip.to_string(); } );
There is two things in your code that will not work.
First, when passing a lambda function as argument, I suggest using Template. The standard library on Microsoft seems to use this method for std::for_each for example.
And :
When function template has a return type, which cannot be deduced from arguments, or when function template doesn't have any argument, the type cannot be deduced by the compiler. This function will require template type argument specification.
Take a look at this example :
template<class Tout, class Tin, class Fun>
// ^^^^^^^^^^^
// Note that I changed the order of the types
std::vector<Tout> map( const std::vector<Tin>& in,
Fun mapper ) {
// ^^^^^^^^^^
std::vector<Tout> ret;
for( auto elem : in ) {
ret.push_back( mapper( elem ) );
}
return ret;
}
int main()
{
std::vector<int> bars /* = ... */;
std::vector<float> foos = map<float>( bars, []( int ) { return 1.0f; } );
// ^^^^^^^ Specify the type Tout
system( "pause" );
return 0;
}
EDIT :
Like it is said in the comment, we can use decltype and std::decay to not have to explicitly specify the result of the function :
template<class Tin, class Fun> // no Tout
// ^^^^^^^^^^^
auto map( const std::vector<Tin>& in, Fun mapper )
//^^^^ ^^^^^^^^^^
-> std::vector<typename std::decay< decltype( mapper( in.front() ) )>::type > {
std::vector<typename std::decay< decltype( mapper( in.front() ) )>::type > ret;
for( auto elem : in ) {
ret.push_back( mapper( elem ) );
}
return ret;
}
int main()
{
std::vector<int> bars /* = ... */;
std::vector<float> foos = map( bars, []( int ) { return 1.0f; } );
// No specification
system( "pause" );
return 0;
}
Let's explain a little bit.
First we will use the late-specified return type syntax. It will allow us to use the parameter names in the return type specification. We start the line with auto and put the return type specification after the parameters using ->.
We will use decltype because the decltype type specifier yields the type of a specified expression. It will be very useful in our case. For example to get the type of the function we passed in parameters, it is just decltype( f( someArg ) ).
Let's state what do we want : The return type of the function should be a vector of the return type of the function passed in argument right ? So we can return std::vector< decltype( mapper( in.front() ) )> and that's it ! (Why the in.front() ? We have to pass a parameter to the function to have a valid expression.)
But here again, we have a problem : std::vector does not allow references. To be certain that it will not be a problem for us, we will use the std::decay meta-function who applies lvalue-to-rvalue, array-to-pointer, and function-to-pointer implicit conversions to the type T, removes cv-qualifiers, remove references, and defines the resulting type as the member typedef type.. That is, if the function returns something like const Foo& it will end in Foo.
The result of all of that : std::vector< typename std::decay< decltype( mapper( in.front() ) )>::type >.
You have to repeat this expression again at the beginning of the function to declare the variable you will return.
Some usefull references about that :
http://en.cppreference.com/w/cpp/types/decay
http://en.wikipedia.org/wiki/Decltype
http://www.cprogramming.com/c++11/c++11-auto-decltype-return-value-after-function.html
http://msdn.microsoft.com/en-us/library/dd537655.aspx
It is not easy to explain, I hope my explanations are understandable.
There's no need to explicitly specify the result of map, it can be deduced. I'm also going to accept any range (something that provides begin and end), simply because doing so is trivial. I could make it even more generic and use the free begin and end versions, but that makes it even more complicated, so I won't.
template <typename Range, typename Func>
auto map(const Range& r, Func f)
-> std::vector<typename std::decay<decltype(f(*r.begin()))>::type> {
std::vector<typename std::decay<decltype(f(*r.begin()))>::type> result;
for (const auto& e : r) {
result.push_back(f(e));
}
// Alternatively:
//std::transform(r.begin(), r.end(), std::back_inserter(result), f);
return result;
}
This isn't exactly trivial code, so let me explain.
First, I use the late-specified return type syntax here: I start the function with auto and put the actual return type after the parameters, indicated with ->. This allows me to use parameter names in the return type specification, which is very useful in the decltype stuff I'm doing next.
So what do we actually want? We want a vector of whatever f returns when called with elements of r. What is that? Well, we can use decltype to find out. decltype(expr) gives you the type of expr. In this case, the expression is a call to f: decltype(f(arguments)). We have one argument: an element of the range. The only things a range gives us are begin() and end(), so let's use that: dereference begin() to get the actual value. The expression is now decltype(f(*r.begin())). Note that this is never actually evaluated, so it doesn't matter if the range is empty.
Ok, this gives us the return type of the function. But if we write std::vector<decltype(...)> that leaves us with a problem: the return type of the function could be a reference, but a vector of references is not valid. So we apply the std::decay metafunction to the return type, which removes references and cv-qualifiers on the referenced type, so if the function returns const Foo&, the result of std::decay is just Foo.
This leaves me with the final return type std::vector<typename std::decay<decltype(f(*r.begin()))>::type>.
And then you get to repeat the same thing to declare the actual variable holding the return value. Unfortunately, because there's no way to put type aliases at any reasonable point, you can't get rid of this.
Anyway, there was another problem with your original code, and that was declaring the loop variable as auto. If you call this map with a vector<Bar>, you end up with the loop
for (Bar b : in) { ... }
Notice how your loop variable is a value? This means that you copy every element of in to a local variable. If a Bar is expensive to copy, this is a serious performance issue. And if your transformation relies on the object identity of its argument (e.g. you return a pointer to a member), then your performance issue has become a correctness issue, because the resulting vector is full of dangling pointers. This is why you should use const auto& in the loop, or just use the std::transform algorithm internally, which gets this right.

Resources