web-dev-qa-db-fra.com

Résolution de surcharge pour les fonctions héritées

Je veux avoir une structure qui prend un nombre arbitraire de lambdas et servir de point d'appel central pour tous leurs opérateurs d'appel.

Si l'opérateur d'appel est appelé avec une liste d'arguments qui ne correspond à aucun des lambdas donnés lors de la construction, un opérateur d'appel par défaut doit être appelé.

Je pensais que le code suivant accomplirait exactement cela. L'opérateur d'appel pour chaque lambda est "levé" dans la classe Poc via 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;
}

Lorsque je n'ai pas l'opérateur d'appel par défaut dans la structure, tout fonctionne comme prévu (avec des listes d'arguments valides). Si je l'ajoute à la structure (comme dans le code ci-dessus), l'opérateur par défaut est appelé à chaque fois, quels que soient les arguments avec lesquels je l'appelle.

À ma connaissance, les opérateurs d'appel lambda et l'opérateur d'appel structs (par défaut) sont présents dans la même portée. Par conséquent, ils doivent tous être examinés pour la résolution de surcharge. Puisque l'opérateur lamdba est plus spécifique que l'opérateur générique par défaut, il doit être choisi.

Apparemment, ce n'est pas le cas. Pourquoi donc?

J'ai testé sur Microsoft Visual C++ , Clang et GCC (tous dans leurs dernières versions).

Modifier:

56
LcdDrm

C'est simple quand vous le repérez: votre opérateur n'est pas qualifié de const-, tandis que celui de lambda l'est (sauf si vous définissez le lambda comme mutable). Par conséquent, c'est une meilleure correspondance pour votre instance non constante de Poc.

Ajoutez simplement le const manquant:

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