mercredi 24 juillet 2019

Move-constructing a C++11 thread from a thread object argument created from a callable argument

In a C++11 initialization list, I'm trying to move-construct a thread from a thread object that was created elsewhere and passed to the constructor. I'm also trying to create the thread object using a passed-in callable argument. I'm not having any luck.

The following (invalid) code will, hopefully, indicate what I'm trying to do:

$ cat a.cpp
#include <map>
#include <thread>

class Thing {
    int i;
};

class Impl {
    class Entry {
        Thing         thing;
        std::thread   thread;

    public:
        template<class F>
        Entry(Thing& thing, F&& func)
            : thing(thing)
            , thread(func) {
        }
    };

    class ThingMap {
        std::map<Thing, Entry> map;

    public:
        template<class F>
        void add(Thing& thing, F&& func) {
            map.emplace({thing, {thing, func}});
        }
    };

    ThingMap things;

    void execute() {
    }

public:
    void activate(Thing& thing) {
        things.add(thing, [this]{execute();});
    }
};
$ 

Here are the errors from my g++ 4.8.5 compiler:

$ g++ -std=c++11 -c a.cpp
a.cpp: In instantiation of ‘void Impl::ThingMap::add(Thing&, F&&) [with F = Impl::activate(Thing&)::__lambda0]’:
a.cpp:38:45:   required from here
a.cpp:27:13: error: no matching function for call to ‘std::map<Thing, Impl::Entry>::emplace(<brace-enclosed initializer list>)’
             map.emplace({thing, {thing, func}});
             ^
a.cpp:27:13: note: candidate is:
In file included from /usr/include/c++/4.8.2/map:61:0,
                 from a.cpp:1:
/usr/include/c++/4.8.2/bits/stl_map.h:540:2: note: std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::emplace(_Args&& ...) [with _Args = {}; _Key = Thing; _Tp = Impl::Entry; _Compare = std::less<Thing>; _Alloc = std::allocator<std::pair<const Thing, Impl::Entry> >; typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator = std::_Rb_tree_iterator<std::pair<const Thing, Impl::Entry> >]
  emplace(_Args&&... __args)
  ^
/usr/include/c++/4.8.2/bits/stl_map.h:540:2: note:   candidate expects 0 arguments, 1 provided
$ 

Any and all suggestions on how to fix the code will be gratefully appreciated. Please leave the structure alone, however, it's there for a reason.

Aucun commentaire:

Enregistrer un commentaire