Using Visual Studio 2013 RC and C++, I'm trying to pass an std::unique_ptr to a function that has been bound using std::bind. However, I'm having trouble because VS doesn't seem to like it when I try this. Here's what I'm trying to compile:
#include <memory>
#include <iostream>
#include <functional>
void func(std::unique_ptr<int> arg)
{
std::cout << *arg << std::endl;
}
int main()
{
std::function<void (std::unique_ptr<int>)> bound =
std::bind(&func, std::placeholders::_1);
std::unique_ptr<int> ptr(new int(42));
bound(std::move(ptr));
return 0;
}
This compiles in GCC 4.8.1, but not in VS2013 RC. I've always had problems with move semantics in VS, but I'd really like to use std::unique_ptr instead of std::shared_ptr or raw pointers.
One workaround I've found is to change the function signature to accept an std::unique_ptr&, which does compile in VS and GCC, but doesn't make the intent of func taking ownership of the std::unique_ptr particularly clear, and also prevents me from safely asynchronously calling the function unless I do something particularly ugly:
#include <memory>
#include <iostream>
#include <functional>
#include <future>
#include <string>
void func(std::unique_ptr<int>& arg)
{
std::cout << *arg << std::endl;
}
int main()
{
std::function<void (std::unique_ptr<int>&)> bound =
std::bind(&func, std::placeholders::_1);
std::unique_ptr<int> ptr(new int(42));
std::promise<void> prom;
std::async(
[&bound, &ptr, &prom]
{
std::unique_ptr<int> movedPtr = std::move(ptr);
prom.set_value();
bound(std::move(movedPtr));
});
prom.get_future().wait();
// Wait here
std::string dummy;
std::cin >> dummy;
}
Is there a way to get around this without changing func's signature?
Thanks!
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)); };
You have to move the parameter into the bound call to func also. Not only in the invocation of bound
bound(std::move(ptr));
but also in the binding:
std::function<void(std::unique_ptr<int>)> bound =
std::bind(func,
std::bind(std::move<std::unique_ptr<int>&>,
std::placeholders::_1));
This is compiling in VS2013 (update 4) for me.
Functions bound with std::bind do not forward arguments, it copies them to the function. As a result, std::bind doesn't work with move-only types as of c++11. This problem is the idea behind proposals for "more perfect forwarding" (like this one). There's a newer one, but I can't seem to find it right now.
Related
I am working on an old source code project which originally was written using MSVC 2008 and Boost 1.42, today I'm trying to port this to MSVC 2017 with Boost 1.73
There are many issues to resolve, one of which is below:
Severity Code Description Project File Line Suppression State
Error C3536 'binding': cannot be used before it is initialized Process Control Service Group processscope.cpp 197
The line that this occurs on:
auto binding = boost::bind(&IProcessChangeObserver::notify, _1, m_scope, change);
std::for_each(observers.begin(), observers.end(), binding);
Originally the assignment to binding was inline as the third parameter, it gives the same error. I can see why this is a problem, I cannot see why it ever worked?
Is there another way to write the above without the triggering a warning?
I've tried replacing with a standard loop:
for( std::list<boost::intrusive_ptr<IProcessChangeObserver> >::iterator itProc=objservers.begin();
itProc!=objservers.end(); itProc++ ) {
boost:bind(&IProcessChangeObserver::notify, itProc, m_scope, change);
}
To be honest I'm not 100% sure if this is a like for like replacement?
I have a suspicion the real problem is with binding which is likely not correctly initialized. There's bound to be more compiler messages about that.
It could be because Boost Bind stopped putting the _1 placeholders in the global namespace by default. You might detect this by adding -DBOOST_BIND_GLOBAL_PLACEHOLDERS to the compiler flags. However, heed the advice from the code:
BOOST_PRAGMA_MESSAGE(
"The practice of declaring the Bind placeholders (_1, _2, ...) "
"in the global namespace is deprecated. Please use "
"<boost/bind/bind.hpp> + using namespace boost::placeholders, "
"or define BOOST_BIND_GLOBAL_PLACEHOLDERS to retain the current behavior."
)
Minimal repro
See if you can reproduce with this minimal reproducer (I can't but I don't have access to the requisite versions ofr MSVC/Boost):
Live ON Coliru - GCC
Live On Rextester - MSVC
#include <algorithm>
#include <iostream>
#include <list>
#include <boost/bind/bind.hpp>
using namespace boost::placeholders;
#include <boost/intrusive_ptr.hpp>
#include <boost/smart_ptr/intrusive_ref_counter.hpp>
struct Scope {};
struct Change {};
namespace MyLib {
struct IProcessChangeObserver
: boost::intrusive_ref_counter<IProcessChangeObserver>
{
virtual ~IProcessChangeObserver() = default;
virtual void notify(Scope, Change) = 0;
};
struct Obs1 : IProcessChangeObserver {
void notify(Scope, Change) override { std::cout << "Obs1\n"; }
};
struct Obs2 : IProcessChangeObserver {
void notify(Scope, Change) override { std::cout << "Obs2\n"; }
};
}
using ObserverPtr = boost::intrusive_ptr<MyLib::IProcessChangeObserver>;
int main() {
using namespace MyLib;
std::list<ObserverPtr> observers {
new Obs1(), new Obs2(), new Obs1(),
};
Scope m_scope;
Change change;
auto binding = boost::bind(&IProcessChangeObserver::notify, _1, m_scope, change);
std::for_each(observers.begin(), observers.end(), binding);
}
Prints
Obs1
Obs2
Obs1
The actual fix was just to change _1 to std::placeholders::_1
I'm readin Scott Meyrse C++ and now I'm at the section about deigning interfaces. The following code is supposed to be invalid:
std::tr1::shared_ptr<Investment> // attempt to create a null
pInv(0, getRidOfInvestment); // shared_ptr with a custom deleter;
// this won’t compile
He gave the following explanation:
The tr1::shared_ptr constructor insists on its first parameter being a
pointer, and 0 isn’t a pointer, it’s an int. Yes, it’s convertible to
a pointer, but that’s not good enough in this case; tr1::shared_ptr
insists on an actual pointer.
I tried similar example myself http://coliru.stacked-crooked.com/a/4199bdf68a1d6e19
#include <iostream>
#include <memory>
struct B{
explicit B(void *){ }
};
void del(int*){ }
int main()
{
B b(0);
std::shared_ptr<int*> ptr(0, del);
}
and it compiles and runs fine even in spite of passing 0 as the first argument.
What did he mean actually? Isn't that relevant already?
One is from #include <tr1/memory>; the other is from #include <memory>. There is a difference:
http://coliru.stacked-crooked.com/a/f76ea0ef17227d9d
#include <iostream>
#include <tr1/memory>
#include <memory>
struct B{
explicit B(void *){ }
};
void del(int*){ }
int main()
{
B b(0);
std::tr1::shared_ptr<int*> ptr(0, del);
std::shared_ptr<int*> ptr2(0, del);
}
It gives the error for the tr1 version but not the current standard version.
I'm coming back to c++ from a long absence, and am picking up c++11 and boost::asio at the same time.
After GotW #93 and #94, I'm naturally fired up about using auto.
Imagine my disapointment when this doesn't compile:
auto io = boost::asio::io_service{};
but I must use this instead:
boost::asio::io_service io{};
Why does the second compile, but the first not? The error I'm getting is
Call to implicitly-deleted copy constructor of 'boost::asio::io_service'
boost::asio::deadline::timer exhibits the same behavior, but boost::posix_time::seconds does not.
(I'm using xcode + clang + boost 1_55_0).
Full compiling example, modified from the boost asio tutorial:
#include <iostream>
#include <memory>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
namespace asio = boost::asio;
int main(int argc, const char * argv[]) {
using error_code = const boost::system::error_code;
asio::io_service io{};
asio::deadline_timer t{io, boost::posix_time::seconds{2}};
int count = 0;
std::function<void (const error_code&)> fn = [&](const error_code& e) {
if (count < 5) {
std::cout << "Hello World" << std::endl;
++(count);
t.expires_at(t.expires_at() + boost::posix_time::seconds{1});
t.async_wait(fn);
}
};
t.async_wait(fn);
io.run();
std::cout << "Final count is " << count << std::endl;
return 0;
}
The class asio::io_service derives from noncopyable, which means the copy constructor has been intentionally made inaccessible. This statement won't work for the same reason:
boost::asio::io_service io = boost::asio::io_service{};
In this instance, the problem is not because of the auto keyword, but lack of access to the required constructor. The tutorial code uses the normal constructor, which is public, and so compiles fine.
The error is pretty self-explanatory, it has nothing to do with the use of auto. The following code will produce a similar error message:
struct foo
{
foo() = default;
foo(foo const&) = delete;
};
foo f = foo{};
The last line above requires an accessible copy-constructor (even if the compiler elides the copy).
boost::asio::io_service's copy-constructor is implicitly deleted, probably due to the presence of one or more non-copyable data members or base classes. You already have the right solution to fix the error:
asio::io_service io{};
Lyrics:
I try to implement a task pool over MPI. So I need some kind of RPC but one that would work between different parts of my program, meaning processor A wants processor B to call function C with argument D. We can not pass pointers to functions between processes like we do with threads, so we need some wrapper container to hold our function pointers at each process instance. All inside one source file\one program... So I started wondering about How to store functional objects with different signature in a container. My API Idea back then was wrong - it is better to define all functions in function pool at that pool construction (at least it shall be much easier to implement). But while implementing I faced next trouble:
Problem:
Such simple code (function_types, mpl::vector, variant):
#include <boost/function_types/function_type.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/variant.hpp>
#include <iostream>
#include <string>
template <class T>
int append(T val)
{
std::cout << "hello";
return 0;
}
int main()
{
boost::variant<boost::function_types::function_type< boost::mpl::vector<int,int> >::type , boost::function_types::function_type< boost::mpl::vector<int,std::string> >::type > a;
return 0;
}
Will not compile falling with:
Error 1 error C2066: cast to function type is illegal c:\program files\boost\include\boost\variant\variant.hpp 1231 1
And looking at source we see:
this code block:
variant()
{
// NOTE TO USER :
// Compile error from here indicates that the first bound
// type is not default-constructible, and so variant cannot
// support its own default-construction.
//
new( storage_.address() ) internal_T0();
indicate_which(0); // zero is the index of the first bounded type
}
So I wonder: How to get around this error?
Also I tried:
#include <boost/function_types/function_type.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/variant.hpp>
#include <boost/function.hpp>
#include <iostream>
#include <string>
template <class T>
int append(T val)
{
std::cout << "hello";
return 1;
}
int main()
{
boost::variant< boost::function<int (std::string) >, boost::function<int (int) > > a;
a= &append<int>;
return 0;
}
Which fails with:
Error 1 error C2668: 'boost::detail::variant::make_initializer_node::apply<BaseIndexPair,Iterator>::initializer_node::initialize' : ambiguous call to overloaded function c:\program files\boost\include\boost\variant\variant.hpp 1330
Any Ideas on how to make boost.variant hold functions?
Of course we can play with shared pointers to functors like so:
#include <boost/variant.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <string>
template <class in, class out>
struct s_append
{
out operator()(in val) {
std::cout << "hello";
return out();
}
};
int main()
{
boost::variant<boost::shared_ptr<s_append<int, int> >, boost::shared_ptr< s_append<std::string, int> > > a;
boost::shared_ptr<s_append<int, int> > b(new s_append<int, int> );
a=b;
return 0;
}
and it would compile but resulting API sucks - you have to 1) create functors for all functions you want to use (meaning limit there use of current process scope); 2) use shared_pointers and so I don't really even get how to call functions nested that way (simple first guess (*a)(22); just won't compile =( and API starts to be as bad as we would have using Boost.Any).
Try inserting a dummy type as the first argument of the variant. As the comment you found explains, only the first type in the variant is used for the variant's own default constructor. You could use an empty struct type for this (struct NoFunction {};).
That said, you may have been onto something with the idea to use boost::functions as the types in the variant...they are default-constructible at least. I'm not sure what the other error you had from that approach was caused by, but just wanted to let you know you could pursue that angle more if you can't use the dummy-type workaround I mentioned.
Is it somehow possible to pass an std::unique_ptr as a parameter to a boost::thread constructor? If not, what is the best workaround?
A small example:
// errors: g++ uniqueptr_thread.cpp -std=c++0x
#include <iostream>
#include <memory>
#include <boost/thread.hpp>
class TestThread{
public:
void operator()(std::unique_ptr<int> val){
std::cout << "parameter: " << val << std::endl;
}
};
int main(int argc, char* argv[]){
std::unique_ptr<int> ptr(new int(5));
boost::thread th( new TestThread(), std::move(ptr));
}
This compiles and runs for me:
#include <iostream>
#include <memory>
#include <thread>
class TestThread{
public:
void operator()(std::unique_ptr<int> val){
std::cout << "parameter: " << *val << std::endl;
}
};
int main()
{
std::unique_ptr<int> ptr(new int(5));
std::thread th( TestThread(), std::move(ptr));
th.join();
}
But it has to be in C++0x mode. I don't know if the boost move emulation is good enough to do this or not.
A std::unique_ptr is, as the name suggests, unique. There can be only one!
Now, if your thread function takes a std::unique_ptr&&, and you use std::move to move the parameter in the thread function, then you can pass the std::unique_ptr. But then your copy will be empty, since you moved it to the other thread.
If std::move does not work, then your compiler or standard library may have bugs in it. I imagine that transferring ownership across threads like this isn't a common occurrence. And C++11 is still fairly new.
Are you sure your problem is with the unique_ptr? Why does your example use new to create your functor? That line should just read:
boost::thread th(TestThread(), std::move(ptr));