How to pass lambda to a lambda? - c++

I have not managed to find why this code does not
work:
#include <iostream>
#include <functional>
using namespace std;
int main()
{
auto xClosure = [](const function<void(int&)>& myFunction) {
myFunction(10);};
xClosure([]
(int& number) -> void
{cout<<number<<endl;
});
return 0;
}
It returns:
g++ test.cc -o test -std=c++14
test.cc:9:5: error: no matching function for call to object of type 'const function<void
(int &)>'

This has nothing to do with lambdas:
void test(const function<void(int&)>& myFunction) {
myFunction(10);
}
this fails to compile for the same reason; you cannot bind the literal 10 to an int&.
Maybe you meant
const function<void(int)>& myFunction
doing so and also modifying the signature of your lambda should make your code compile.

Related

explicit conversion to std::function

I'm trying to define explicit conversion from some class to std::function like this:
#include <functional>
class ExpInt { private:
const int value;
public:
ExpInt(const int v):value(v){}
explicit operator std::function<int (void)> ()
{
return [=](void){ return value; };
}
};
int main(int argc, char **argv)
{
auto e = new ExpInt(44);
auto f = static_cast<std::function<int (void)>>(e);
return 0;
}
But when I compile it I get the following error:
$ g++ main.cpp -o main
main.cpp: In function ‘int main(int, char**)’:
main.cpp:16:51: error: no matching function for call to ‘std::function<int()>::function(ExpInt*&)’
auto f = static_cast<std::function<int (void)>>(e);
^
The compiler tells you what's wrong:
error: no matching function for call to ‘std::function<int()>::function(ExpInt*&)’
auto f = static_cast<std::function<int (void)>>(e);
^
A pointer to ExpInt is not convertible to std::function<int (void)>. ExpInt would be convertible, so if you simply indirect through the pointer, that would work:
auto f = static_cast<std::function<int (void)>>(*e);
P.S. You leak the dynamic allocation. Avoid using owning bare pointers.

Overload class member function marked const

I am having trouble overloading class member functions that are marked const, while there is no problem when the functions are not marked const. Also the overload itself works fine in pure C++.
The following fails
#include <vector>
#include <pybind11/pybind11.h>
class Foo
{
public:
Foo(){};
std::vector<double> bar(const std::vector<double> &a) const
{
return a;
}
std::vector<int> bar(const std::vector<int> &a) const
{
return a;
}
};
namespace py = pybind11;
PYBIND11_MODULE(example,m)
{
py::class_<Foo>(m, "Foo")
.def("bar", py::overload_cast<const std::vector<double>&>(&Foo::bar));
}
Compiled using:
clang++ -O3 -shared -std=c++14 `python3-config --cflags --ldflags --libs` example.cpp -o example.so -fPIC
Gives error:
...
no matching function for call to object of type 'const detail::overload_cast_impl<const vector<double, allocator<double> > &>'
.def("bar", py::overload_cast<const std::vector<double>&>(&Foo::bar));
...
Whereas the code works when I remove the const mark of the functions.
How should I perform this overload?
There is a special tag for const overloaded methods.
namespace py = pybind11;
PYBIND11_MODULE(example,m)
{
py::class_<Foo>(m, "Foo")
.def("bar", py::overload_cast<const std::vector<double>&>(&Foo::bar, py::const_));
}

gcc fails to compile generic lambda with this capture [duplicate]

This question already has an answer here:
Calling `this` member function from generic lambda - clang vs gcc
(1 answer)
Closed 6 years ago.
I cannot compile the following program with gcc 6.1:
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
class Foo
{
public:
void apply() const
{
std::for_each(std::cbegin(bars_), std::cend(bars_), [this] (const auto& x) { print(x); });
}
private:
std::vector<std::string> bars_;
void print(const std::string& x) const
{
std::cout << x << ' ';
}
};
int main()
{
Foo foo {};
foo.apply();
return 0;
}
The error message is:
error: cannot call member function 'void Foo::print(const string&) const' without object
std::for_each(std::cbegin(bars_), std::cend(bars_), [this] (const auto& x) { print(x); });
^~~~~
Changing const auto& x to const std::string& x makes the program compile.
Changing print(x) to this->print(x) makes the program compile.
All versions compile with Clang (Apple LLVM version 7.3.0 (clang-703.0.31)).
Is this a compiler bug?
This is a documented gcc bug which as of August 2016 has not been fixed yet.
I don't think the compiler is obliged to deduce the type being passed to the lambda inside the for_each function, bear in mind this function has already been compiled, how can the compiler know what the for_each function is going to pass to the lambda after it passed the lambda in?
I don't know why. But the solution is to specify which print it should use:
std::for_each(std::cbegin(bars_), std::cend(bars_), [this] (const auto& x) { this->print(x); });
With this it compiles.
See: http://coliru.stacked-crooked.com/a/1177b09a3e5863e2

no known conversion for templated vs const non-templated vector

In my actual code, I included a library, and as soon as I did that, it started crashing. I managed to sort of extract some of that code into this minimal example, that demonstrates the same kind of error:
// g++ -std=c++11 -g -o test-classcall.exe test-classcall.cpp
#include <iostream>
#include <vector>
#include <stdio.h>
class Cat
{
public:
int Age;
Cat() : Age(0) {}
};
std::vector<Cat> myPCats;
typedef std::vector<Cat> TDVectCats;
TDVectCats myTDCats;
void loopSomeCats() {
printf("this function just to cause searching for matching calls\n");
}
void loopSomeCats(TDVectCats& incats) {
std::vector<Cat>::iterator iter;
for(iter = incats.begin(); iter != incats.end(); iter++) {
printf("hm\n");
}
}
const std::vector<Cat> & getSomeCats() {
return myPCats;
}
void doSomething() {
loopSomeCats(getSomeCats());
}
int main() {
myTDCats.push_back(Cat());
myTDCats.push_back(Cat());
myPCats.push_back(Cat());
doSomething();
std::cout << "Hello World! " << std::endl;
return 0;
}
The result is:
$ g++ -std=c++11 -g -o test-classcall.exe test-classcall.cpp
test-classcall.cpp: In function ‘void doSomething()’:
test-classcall.cpp:36:29: error: no matching function for call to ‘loopSomeCats(const std::vector<Cat>&)’
loopSomeCats(getSomeCats());
^
test-classcall.cpp:36:29: note: candidates are:
test-classcall.cpp:20:6: note: void loopSomeCats()
void loopSomeCats() {
^
test-classcall.cpp:20:6: note: candidate expects 0 arguments, 1 provided
test-classcall.cpp:24:6: note: void loopSomeCats(TDVectCats&)
void loopSomeCats(TDVectCats& incats) {
^
test-classcall.cpp:24:6: note: no known conversion for argument 1 from ‘const std::vector<Cat>’ to ‘TDVectCats& {aka std::vector<Cat>&}’
What especially confuses me, is the last "no known conversion for argument 1 from ‘const std::vector<Cat>’ to ‘TDVectCats& {aka std::vector<Cat>&}’", as if it cannot convert a vector of something, into the vector of the same something, just because of typedef? Or it maybe has to do with the const - but I simply cannot see what I need to change, in order to have a call like loopSomeCats(getSomeCats()); succeed...
You can't pass a reference to a const object to a non-const reference.
loopSomeCats takes a std::vector<Cat>& as argument, and you want to pass a const std::vector<Cat>& to it, but that's not possible.
The const would mean that you don't want anyone to modify the return value, but if you pass it to a function which just takes a non-const reference, then theoretically the function can modify the reference, and you don't want that.
You should drop the const if you want the return value to be modified.

how to bind vector.resize

I try to use boost::bind with std::vector<>::resize.
But the following code won't compile:
#include <boost/bind.hpp>
#include <vector>
using namespace boost;
int main(){
typedef std::vector<double> type;
type a;
bind(&type::resize, _1, 2)(a);
return 0;
}
So, how can I do this?
Thanks!
boost version 1.53
gcc version 4.8 or 4.6
*Edit: * The above code works with -std=c++11. In fact, my original problem is this:
#include <boost/bind.hpp>
#include <blitz/array.h>
#include <vector>
using namespace boost;
using namespace blitz;
int main(){
typedef Array<double, 1> type;
type a;
//a.resize(4) is ok;
bind(&type::resize, _1, 2)(a);
return 0;
}
My compile command is:
g++ t.cpp -I path/include/ -std=c++11 -L path/lib/ -l blitz
resize might be an overloaded function (in C++11 it has to be) so you need to tell the compiler which overload you want. For the one argument form, this should work in C++11:
bind(static_cast<void (type::*)(type::size_type)>(&type::resize), _1, 2)(a);
Or more readably:
typedef void (type::*resize_signature)(type::size_type);
bind(static_cast<resize_signature>(&type::resize), _1, 2)(a);
If it's not an overloaded function (as with GCC in C++03 mode) then it takes two arguments (one has a default value) and you need to supply the second argument because bind can't use default arguments:
typedef void (type::*resize_signature)(type::size_type, const value_type&);
bind(static_cast<resize_signature>(&type::resize), _1, 2, 0.0)(a);
Unfortunately this C++03 version isn't portable, implementations are allowed to use a single function or a pair of overloads. To make it portable, or to work with other types such as Array you can wrap the call in a custom functor that calls resize, so you don't need to know the exact signature:
typename<class VecT>
struct resizer<VecT> {
void operator()(VecT& v, unsigned n) const { v.resize(n); }
};
// ...
bind(resizer<type>(), _1, 2)(a);
Or in C++11 just use a lambda expression instead of bind:
auto resize = [](type& v) { v.resize(2); };
resize(a);