http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53202
Jonathan Wakely <redi at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|ASSIGNED |NEW CC| |jason at gcc dot gnu.org Component|libstdc++ |c++ AssignedTo|redi at gcc dot gnu.org |unassigned at gcc dot | |gnu.org --- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> 2012-05-03 00:45:01 UTC --- Here's a reduced version that only needs -std=c++11 and not -pthread #include <tuple> template<typename Callable> struct Bind_simple { explicit Bind_simple(const Callable& callable) : _M_bound(callable) { } Bind_simple(const Bind_simple&) = default; Bind_simple(Bind_simple&&) = default; auto operator()() -> decltype((*(Callable*)0)()) { return std::get<0>(_M_bound)(); } private: std::tuple<Callable> _M_bound; }; template<typename Callable> Bind_simple<Callable> bind_simple(Callable& callable) { return Bind_simple<Callable>(callable); } struct thread { struct ImplBase { }; template<typename T> struct Impl : ImplBase { T t; Impl(T&& t) : t(std::move(t)) { } }; template<typename T> thread(T& t) { auto p = make_routine(bind_simple(t)); p->t(); delete p; } template<typename Callable> Impl<Callable>* make_routine(Callable&& f) { return new Impl<Callable>(std::forward<Callable>(f)); } }; class background_hello { public: background_hello() { __builtin_printf("default ctor called, this=%p\n", this); } background_hello(const background_hello &) { __builtin_printf("copy ctor called\n"); } background_hello(background_hello &&) { __builtin_printf("move ctor called\n"); } void operator ()() const { __builtin_printf("void background_hello::operator()() called, this=%p\n", this); } ~background_hello() { __builtin_printf("destructor called, this=%p\n", this); } }; int main() { background_hello bh; thread t(bh); } This still produces the wrong result: default ctor called, this=0x7fffe4a2c3bf destructor called, this=0x7fffe4a2c38f void background_hello::operator()() called, this=0xd9d028 destructor called, this=0xd9d028 destructor called, this=0x7fffe4a2c3bf Looking at the gimple dump I see that the thread::Impl<Bind_simple<background_hello()>> constructor doesn't initialize its Bind_simple member: thread::Impl<T>::Impl(T&&) [with T = Bind_simple<background_hello>] (struct Impl * const this, struct Bind_simple & t) { struct Bind_simple * D.8909; thread::ImplBase::ImplBase (this); try { } catch { D.8909 = &this->t; Bind_simple<background_hello>::~Bind_simple (D.8909); } } If the Bind_simple object isn't move-constructed then its background_hello object won't be either, which explains the missing constructor calls. If Bind_simple<Callable> stores a Callable directly instead of as tuple<Callable> then the problem goes away and I see three constructors called. I think at this point it looks like a G++ issue