web-dev-qa-db-ja.com

継承された関数のオーバーロード解決

任意の数のラムダを取り、すべての呼び出し演算子の中心的な呼び出しポイントとして機能する構造体が必要です。

呼び出し演算子が、構築時に指定されたラムダのいずれとも一致しない引数リストで呼び出された場合、デフォルトの呼び出し演算子を呼び出す必要があります。

私は次のコードがまさにこれを達成すると思った。すべてのラムダの呼び出し演算子は、Pocを介してusingクラスに「リフト」されます。

template <typename ...Lambdas>
struct Poc : Lambdas...
{
    using Lambdas::operator() ...; // Lift the lambda operators into the class

    template <typename ...Ts>
    auto operator() (Ts...)
    {
        std::cout << "general call" << std::endl;
    }
};

// Deduction guide
template <typename ...Ts>
Poc(Ts... ts)->Poc<Ts...>;

int main()
{
    auto l_int = [](int) {std::cout << "int" << std::endl; };

    Poc poc{l_int};
    poc(1);//calls the default operator. why?

    return 0;
}

構造体にデフォルトの呼び出し演算子がない場合、すべてが期待どおりに機能します(有効な引数リストを使用)。 (上記のコードのように)構造体に追加すると、呼び出す引数に関係なく、デフォルトの演算子が毎回呼び出されます。

私の理解では、lambda-call-operatorsとstructs(デフォルト)call-operatorは同じスコープ内に存在します。したがって、それらはすべてオーバーロード解決のために見られるべきです。 lamdba-operatorは汎用のデフォルト演算子よりも具体的であるため、選択する必要があります。

どうやらそうではありません。何故ですか?

Microsoft Visual C++Clang 、および [〜#〜] gcc [〜#〜] (すべて最新バージョン)でテストしました。

編集:

  • MSVC 15.8.9
  • GCC 9.0.0( Wandbox 経由)
  • Clang 8.0.0( Wandbox 経由)
56
LcdDrm

見つけたときは簡単です。演算子はconstで修飾されていませんが、 ラムダの1 は(ラムダをmutableとして定義していない限り)です。したがって、Pocの非constインスタンスに適しています。

Missing constを追加するだけです:

auto operator() (Ts...) const
43
Quentin