8

submitAsyncテンプレートstd::functionをパラメーターとして受け入れる関数がありました。

template <typename Ret, typename... Args>                                                                                                                                                     
Future<Ret> submitAsync(const function<Ret (Args...)> &func, Args&&... args);

ただし、ラムダを渡すときに暗黙的なテンプレート引数の推定が機能していませんでした (ここでの問題に似ているため、関数をテンプレート パラメーターとして受け入れる、より一般的な関数を作成し、それを元の関数に渡す必要がありました。

template <typename Func, typename... Args>
auto submitAsync(Func &&func, Args&&... args) -> // Line 82, where the strange error occurs
    Future<
        typename enable_if<
            is_convertible<
                Func, function<decltype(func(args...)) (Args...) >
            >::value ,  decltype(func(args...))
        >::type
    > {
    typedef decltype(func(args...)) ReturnType;
    return submitAsync<ReturnType, Args...>(function<ReturnType (Args...)>(func), forward<Args>(args)...);
}

これは Clang では正常にコンパイルされますが、GCC では次のエラーが返されます。

src/Scheduler.hpp: In substitution of ‘template<class Func, class ... Args> Future<typename std::enable_if<std::is_convertible<Func, std::function<decltype (func(MCServer::Scheduler::startThread::args ...))(Args ...)> >::value, decltype (func(args ...))>::type> MCServer::Scheduler::submitAsync(Func&&, Args&& ...) [with Func = int; Args = {}]’:
src/Scheduler.hpp:91:109:   required from ‘Future<typename std::enable_if<std::is_convertible<Func, std::function<decltype (func(MCServer::Scheduler::startThread::args ...))(Args ...)> >::value, decltype (func(args ...))>::type> MCServer::Scheduler::submitAsync(Func&&, Args&& ...) [with Func = MCServer::MinecraftServer::init()::<lambda()>&; Args = {}; typename std::enable_if<std::is_convertible<Func, std::function<decltype (func(MCServer::Scheduler::startThread::args ...))(Args ...)> >::value, decltype (func(args ...))>::type = int]’
src/MinecraftServer.cpp:237:37:   required from here
src/Scheduler.hpp:82:10: error: expansion pattern ‘#‘nontype_argument_pack’ not supported by dump_expr#<expression error>’ contains no argument packs

これは、まず、次の行を示しています。

return submitAsync<ReturnType, Args...>(function<ReturnType (Args...)>(func), forward<Args>(args)...); 

これは を呼び出す必要がありますがsubmitAsync(const function<Ret (Args...)> &, Args&&...)、実際には を呼び出そうとしていますが、渡されるsubmitAsync(Func &&func, Args&&... args)タイプが であるため、もちろん機能しません。私も理解していないエラーの最後の部分は、おそらくコンパイラのバグである可能性があります (行 82 は、関数の署名の主要部分であり、マークを付けるためにコメントを付けた場所です)。funcintexpansion pattern ‘#‘nontype_argument_pack’ not supported by dump_expr#<expression error>’ contains no argument packs

奇妙なことに、 への呼び出しで明示的なテンプレート パラメータを削除するとsubmitAsync、次の行が置き換えられます。

return submitAsync<ReturnType, Args...>(function<ReturnType (Args...)>(func), forward<Args>(args)...);

これとともに:

return submitAsync(function<ReturnType (Args...)>(func), forward<Args>(args)...);

GCC は正しくコンパイルします。では、引数の推定が許可されている場合は正常に機能するにもかかわらず、テンプレート引数が指定されている場合に GCC が間違った関数を呼び出すのはなぜでしょうか? そして、82行目の奇妙なエラーが何であるかを誰か教えてもらえますか?

編集:言及するのを忘れました、私はGCC 4.7.2を使用しています

EDIT 2:解決策と説明はこちら

4

1 に答える 1

1

さらにテストを行った結果、明示的なテンプレート パラメーターを指定しないと、Clang と GCC の両方が実際には希望どおりに機能しないことがわかりました。どちらの場合も、関数はパラメーターに適合する最初の関数として自分自身を呼び出していました。submitAsyncこれは、関数をテンプレート パラメーターとして受け取る の方が、 を受け取るものよりも適切であるとコンパイラが判断したことが原因でしたconst std::function&submitAsync参照によって関数を取得するように変更した後、正常に動作します。

template <typename Ret, typename... Args>
Future<Ret> Scheduler::submitAsync(function<Ret (Args...)> func, Args&&... args)
于 2012-10-17T20:37:51.477 に答える