3

私はこの単純なクラスを持っています:

struct Worker
{
        Worker() : done{false} {}
        Worker(const Worker& rhs) : done{rhs.done}, qworker{} {}
        Worker(Worker &&rhs) : done{rhs.done}
        {
            qworker = std::move(rhs.qworker);
        }
...
}

これは gcc-4.7.2 で正常にコンパイルされますが、このバージョンを使用しようとするとエラーが発生します

struct Worker
{
        Worker() : done{false} {}
        Worker(const Worker& rhs) : done{rhs.done}, qworker{} {}
        Worker(Worker &&rhs) : done{rhs.done}
                             , qworker{std::move(rhs.qworker)} // <- ERROR
        {
        }
...
}

なんで?

In file included from tlog.cpp:8:0:
log11.hpp: In member function ‘void Log11::Worker::run()’:
log11.hpp:34:29: error: ‘class std::vector<std::function<void()> >’ has no member named ‘pop_front’
In file included from /usr/include/c++/4.7/thread:39:0,
                 from tlog.cpp:3:
/usr/include/c++/4.7/functional: In instantiation of ‘static void std::_Function_handler<void(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes ...) [with _Functor = std::vector<std::function<void()> >; _ArgTypes = {}]’:
/usr/include/c++/4.7/functional:2298:6:   required from ‘std::function<_Res(_ArgTypes ...)>::function(_Functor, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type) [with _Functor = std::vector<std::function<void()> >; _Res = void; _ArgTypes = {}; typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type = std::function<void()>::_Useless]’
log11.hpp:20:78:   required from here
/usr/include/c++/4.7/functional:1926:2: error: no match for call to ‘(std::vector<std::function<void()> >) ()’
4

1 に答える 1

3

C++11 標準によると、std::function任意の引数型を受け入れる制約のないコンストラクター テンプレートがあります。

template<class F> function(F f);

これを言うとqworker{std::move(rhs.qworker)}、最初にコンストラクターを呼び出しようとしますstd::initializer_list<std::function<void()>>。上記の制約のないコンストラクター テンプレートにより、 aは任意のstd::function<void()>から構築できるため、次のように 1 つのメンバーでを取得します。initializer_list

{ std::function<void()>{std::move(rhs.qworker)} }

呼び出し可能なオブジェクトではないため、これは無効ですrhs.qworkerが、関数オブジェクトを呼び出そうとしたときにのみエラーが発生します。

あなたが言うならqworker(std::move(rhs.qworker))、イニシャライザリストコンストラクタは候補ではなく、代わりにムーブコンストラクタが呼び出されます。

標準 ( LWG 2132 )に対する欠陥レポートがありfunction(F)、引数が呼び出し可能なオブジェクトでない限り、コンストラクター テンプレートが呼び出されないようにすることでこれを修正します。これにより、意図したとおりinitializer_list<function<void()>>に作成されず、代わりに移動コンストラクターが呼び出されます。qworker{std::move(rhs.qworker)}GCC 4.7 は LWG 2132 の解像度を実装していませんが、GCC 4.8 は実装しています。

于 2013-04-07T17:13:31.613 に答える