Vc2013: Function from Bind Not Compiling

VC2013: function from bind not compiling

I would normally quote the standard, but the standardese here is particularly dense, so I'll just explain what's happening.

std::bind does something special when you pass an argument to be bound if that argument is a function object returned by a previous call to std::bind. Suppose you do:

auto f = std::bind(foo, std::placeholders::_1);
auto g = std::bind(bar, f, std::placeholders::_1);

Then invoking g(a) is roughly equivalent to

bar(foo(a), a)

rather than

bar(f, a)

Demo.

That is, if you pass something returned by bind to bind as an argument to be bound, what's going to end up being passed to the function you are binding is the result of invoking that bind expression. It's a sort of composition.

However, in your code, you actually don't want the composition to take place. (This composition is what caused g++ to emit 320+ lines of errors when I tried to call your fn_gg on an A. Clang with libc++ printed only 10 lines, thankfully.) You want fn_g to be treated just like an ordinary argument. So you can wrap it in a std::function:

std::function<bool (const std::shared_ptr<S>&, A&)> fn_g = std::bind(getter, this, std::placeholders::_1, std::placeholders::_2);

C++ std::bind to std::function, what went wrong in VS2015?

Your function takes its argument by reference (double &) while your are trying to assign it to the function with signature that takes by value (double).

This has compiled in VS2013 most likely due to conformance bugs (maybe some weird interaction with non-const ref to temporary MSVC extension). Basically it's not a valid C++ code. VS2015 is leagues ahead of previous VSes (VS2017 is even more so) in terms of standard support and conformance so this faulty code is no longer compiling.

Anyway, std::bind is almost entirely obsoleted by lambdas, which should be supported by VS2010+. They produce better code, better warnings/errors, easier to write and debug.

For example, your code could'be rewritten like this:

std::function<double(double)> oFunc = [this](double x){ return myfunction(x); };

Or like this if you actually want to pass by reference:

std::function<double(double &)> oFunc = [this](double &x){ return myfunction(x); };

Notice how shorter and simpler it is.

VS2013 std::function with member function

std::function is required to accept pointers to member functions (definition of INVOKE).

The simplest workaround is to use std::mem_fn instead, or wrap the constructor argument with std::mem_fn:

std::function<void(const Foo&, int)> fun = std::mem_fn(&Foo::bar);

boost::fusion::invoke compiler error with Visual Studio 2013

I suspect the default for BOOST_RESULT_OF has changed for VS2013.

#define BOOST_RESULT_OF_USE_TR1

makes it compile. Chances are this bug is known and has been fixed in trunk, but you might want to report it still

Visual Studio 2013 C++ - Passing std::unique_ptr to a bound function

I had the same problem with VS 2012 recently. I believe this is a bug in MSVC; at least in MSVC++11 the pseudo-variadic expansion seems to forward the parameters by value to some internal function. Seems this hasn't been improved.

As a workaround, I'm using lambdas instead, but another hack is required to make it work:

std::function<void (std::unique_ptr<int>)> bound =
[] (std::unique_ptr<int> arg) { func(std::move(arg)); };

still doesn't compile. But if you add any captured value (even one that isn't used), it compiles:

int x;
std::function<void (std::unique_ptr<int>)> bound =
[x] (std::unique_ptr<int> arg) { func(std::move(arg)); };

std::function not compiling in VS2012

This looks like a bug in VS2012, I have made a bug report here.

For now the following works :

Edit: edited based on Xeo's suggestion to use std::mem_fn

#include <iostream>
#include <functional>

struct Foo {
Foo(int num) : num_(num) {}
void print_add(int i) const { std::cout << num_+i << '\n'; }
int num_;
};

int main()
{
// store a call to a member function
std::function<void(const Foo&, int)> f_add_display = std::mem_fn(&Foo::print_add);
Foo foo(314159);
f_add_display(foo, 1);
}


Related Topics



Leave a reply



Submit