Question

I began implementing N3558 on top of libc++ master (see future here) but am now stuck with an error in functional, which I do not understand.

No matter how I code it, it always fails with the __compressed_pair error. I don't know whether I am missing something or it is a bug in libc++.

The following code:

#include <future>

struct test {
    test() {
        int someint = 0;
        std::promise<void> prom;
        auto fut = prom.get_future();
        fut.then( [this, someint]( std::future<void> future ) {
        } );
    }
};

triggers in clang 3.3:

In file included from /std/include/map:375:
/std/include/functional:993:11: error: no matching constructor for initialization of '__compressed_pair<<lambda at          /std/include/future:1096:14>, std::__1::allocator<<lambda at    /std/include/future:1096:14> > >'
    : __f_(piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__f)),
      ^    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/std/include/functional:1278:26: note: in instantiation of member function 'std::__1::__function::__func<<lambda at /std/include/future:1096:14>, std::__1::allocator<<lambda at /std/include/future:1096:14> >, void ()>::__func' requested here
        ::new (__f_) _FF(_VSTD::move(__f));
                     ^
/std/include/__functional_base:341:37: note: in instantiation of function template specialization 'std::__1::function<void ()>::function<<lambda at /std/include/future:1096:14> >' requested here
return _VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...);
                                ^
/std/include/__config:301:15: note: expanded from macro '_VSTD'
#define _VSTD std::_LIBCPP_NAMESPACE
          ^
/std/include/functional:1691:12: note: in instantiation of function template specialization 'std::__1::__invoke<const <lambda at /std/include/future:1144:17> &, const <lambda at /std/include/future:1096:14> &>' requested here
return __invoke(__f, __mu(get<_Indx>(__bound_args), __args)...);
       ^
/std/include/functional:1761:20: note: in instantiation of function template specialization 'std::__1::__apply_functor<const <lambda at /std/include/future:1144:17>, const std::__1::tuple<<lambda at /std/include/future:1096:14> >, 0, std::__1::tuple<> >' requested here
        return __apply_functor(__f_, __bound_args_, __indices(),
               ^
/std/include/future:1114:3: note: in instantiation of function template specialization 'std::__1::__bind<<lambda at /std/include/future:1144:17>, <lambda at /std/include/future:1096:14> >::operator()<>' requested here
            invoke_bind();
            ^
/std/include/future:1148:22: note: in instantiation of function template specialization 'std::__1::__then<void>::bind<std::__1::future<void>, <lambda at game/Game_local.cpp:1020:9>, <lambda at /std/include/future:1144:17> >' requested here
    return __then<_Rp>::bind( fut, forward<F>(execute_func), move(invoker) );
                        ^
/std/include/future:1527:34: note: in instantiation of function template specialization 'std::__1::__then<void>::bind_async<std::__1::future<void>, <lambda at game/Game_local.cpp:1020:9> >' requested here
{return __then<return_type>::bind_async( *this, std::forward<Function>(func) );}
                             ^
game/local.cpp:1020:3: note: in instantiation of function template specialization 'std::__1::future<void>::then<<lambda at game/Game_local.cpp:1020:9> >' requested here
    .then( [this, someint]( std::future<void> future ) {
     ^
/std/include/memory:2371:31: note: candidate constructor not viable: requires 0 arguments, but 3 were provided
_LIBCPP_INLINE_VISIBILITY __compressed_pair() {}
                          ^
/std/include/memory:2372:40: note: candidate constructor not viable: requires single argument '__t1', but 3 arguments were provided
_LIBCPP_INLINE_VISIBILITY explicit __compressed_pair(_T1_param __t1)
                                   ^
/std/include/memory:2374:40: note: candidate constructor not viable: requires single argument '__t2', but 3 arguments were provided
_LIBCPP_INLINE_VISIBILITY explicit __compressed_pair(_T2_param __t2)
                                   ^
/std/include/memory:2376:31: note: candidate constructor not viable: requires 2 arguments, but 3 were provided
_LIBCPP_INLINE_VISIBILITY __compressed_pair(_T1_param __t1, _T2_param __t2)
                          ^
/std/include/memory:2357:7: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 3 were provided
class __compressed_pair
  ^
/std/include/memory:2357:7: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 3 were provided

Compiling with gcc 4.8 gives a far uglier error message, but it's basically the same.

Could anyone shed some light?

Was it helpful?

Solution

Basically, the interesting part happens when you try to invoke the binding of invoker from bind_async (future:1144). This lambda takes a std::function as an argument, but your binding has a lambda there. So it constructs the parameter from the lambda, which internally creates the type erasure subclass __function::__func. __func stores both the lambda and an allocator, and so as not to waste space when using a stateless allocator, it uses a __compressed_pair. So it tries to construct the compressed_pair with a piecewise_construct constructor, and fails to find one.

Why does it fail to find one? The constructor in question (in memory:2416) is under an #if block, specifically

#ifndef _LIBCPP_HAS_NO_VARIADICS

So I'm going to assume that somehow this symbol got defined in your build. Are you passing -std=c++11 to your compiler? If yes (and how else would all that other stuff compile?), maybe you need to double-check the config of libc++. In any case, you should try adding an #else to that preprocessor block above and putting an #error in there, to make sure that this is really the problem you're having.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top