En C++17, c'est facile à mettre en œuvre un overload(fs...)
fonction qui, étant donné un nombre quelconque d'arguments fs...
satisfaire FunctionObject
, renvoie une nouvelle fonction de l'objet qui se comporte comme une surcharge de fs...
. Exemple:
template <typename... Ts>
struct overloader : Ts...
{
template <typename... TArgs>
overloader(TArgs&&... xs) : Ts{forward<TArgs>(xs)}...
{
}
using Ts::operator()...;
};
template <typename... Ts>
auto overload(Ts&&... xs)
{
return overloader<decay_t<Ts>...>{forward<Ts>(xs)...};
}
int main()
{
auto o = overload([](char){ cout << "CHAR"; },
[](int) { cout << "INT"; });
o('a'); // prints "CHAR"
o(0); // prints "INT"
}
Depuis la overloader
hérite Ts...
, il a besoin de copier ou de déplacer la fonction des objets dans le but de travailler. Je veux quelque chose qui fournit la même surcharge de comportement, mais seulement des références au passé de la fonction des objets.
Nous allons appeler cette fonction hypothétique ref_overload(fs...)
. Ma tentative a été l'aide d' std::reference_wrapper
et std::ref
comme suit:
template <typename... Ts>
auto ref_overload(Ts&... xs)
{
return overloader<reference_wrapper<Ts>...>{ref(xs)...};
}
Semble assez simple, non?
int main()
{
auto l0 = [](char){ cout << "CHAR"; };
auto l1 = [](int) { cout << "INT"; };
auto o = ref_overload(l0, l1);
o('a'); // BOOM
o(0);
}
error: call of '(overloader<...>) (char)' is ambiguous
o('a'); // BOOM
^
La raison pour laquelle il n'a pas de travail est simple: std::reference_wrapper::operator()
est un variadic modèle de fonction, qui ne joue pas bien avec la surcharge.
Afin d'utiliser l' using Ts::operator()...
de la syntaxe, j'ai besoin d' Ts...
pour satisfaire FunctionObject
. Si j'essaie de faire mon propre FunctionObject
wrapper, je rencontre le même problème:
template <typename TF>
struct function_ref
{
TF& _f;
decltype(auto) operator()(/* ??? */);
};
Car il n'y a aucun moyen d'exprimer "compilateur, merci de remplir le ???
avec exactement les mêmes arguments que l' TF::operator()
", j'ai besoin d'utiliser un variadic fonction du modèle, de la résolution de rien.
Je ne peux pas utiliser quelque chose comme boost::function_traits
parce que l'une des fonctions passé de overload(...)
peut être un modèle de fonction ou d'une fonction surchargée de l'objet lui-même!
Donc, ma question est: est-il un moyen de mettre en œuvre un ref_overload(fs...)
fonction qui, étant donné un nombre quelconque d' fs...
objets de fonction, retourne une nouvelle fonction de l'objet qui se comporte comme une surcharge de fs...
, mais se réfère fs...
au lieu de copier/déplacer?