2017-10-09 1 views
0

Compte tenu lambdas avec la structure suivante:surcharge templated lambda sans savoir type d'argument pour les paramètres non basé sur un modèle

auto lambda_1 = [](int x, auto p) -> void {...}; 
auto lambda_2 = [](float x, auto p) -> int {...}; 

Je veux extraire le type de x, ainsi que le type de retour, étant donné un type connu pour p.

Le type de retour est assez simple tant que x est par défaut constructible (que je peux faire une exigence sans problème):

template<typename CB_T> 
void foo(CB_T cb) { 
    using res_type = decltype(cb({}, std::declval<KnownP>())); 
} 

De même, si le second argument n'a pas été inférer, je pouvais facilement trouve le type du premier argument en utilisant quelque chose comme function_traits. Je sais que je peux déclencher la résolution de surcharge comme je le veux, comme en témoigne la façon dont j'extrais le type de résultat sans savoir quel est le type de x, donc je ne vois pas pourquoi je ne devrais pas pouvoir tirer ceci de.

On dirait que j'ai toutes les pièces du puzzle, mais je n'arrive pas à comprendre comment obtenir le type de la fonction surchargée dans ce scénario afin d'extraire le type de x.

Des suggestions?

+0

Quel est le problème que vous essayez de résoudre? En général, cela n'est pas possible sans réflexion. Pour * spécifiquement * lambdas de la forme '[] (T, auto)' sans manivelles SFINAE, c'est possible, mais cela semble étrangement spécifique. – Barry

+0

@Barry c'est huh ... alambiqué ... J'ai besoin de cela pour allouer un tampon temporaire à passer en référence à un sous-processus gabarit pour qu'il se remplisse avant d'appeler le lambda. J'ai besoin que le second paramètre soit modélisé car le type réel sera très opaque, et je ne veux vraiment pas l'imposer aux utilisateurs (je veux aussi que les lambdas soient réutilisables avec différents types opaques). [référence] (https://github.com/FrancoisChabot/abulafia/issues/15) – Frank

+0

@Barry Je voudrais réellement être en mesure d'accepter des foncteurs arbitraires et pas seulement des lambdas, mais demander aux utilisateurs d'envelopper les foncteurs en lambdas est acceptable si nécessaire. (Je veux vraiment soutenir les fermetures si) – Frank

Répondre

1

Dans le cas particulier que vous avez affaire à lambdas que:

  • Prenez deux arguments: le premier est un non-modèle, et dont le second est un modèle
  • un rendement type qui est valable pour tous les paramètres du modèle (par exemple, n'a pas enable_if, etc.)

Ensuite, vous pouvez utiliser un type faux deducer pour le premier argument:

struct arbitrary { template <class T> operator T(); }; 
using res = decltype(cb(arbitrary{}, std::declval<KnownP>())); 

Ou vous pouvez utiliser function_traits pour rechercher le operator() spécifique nous allons utiliser:

using oper = decltype(&CB_T::template operator()<KnownP>); 
using arg0 = typename function_traits<oper>::template arg<0>::type; 
using res = decltype(cb(std::declval<arg0>(), std::declval<KnownP>()); 

Les deux sont vraiment spécifiques à cette disposition particulière lambda cependant.

+0

'decltype (& CB_T :: opérateur de modèle() )' Doy! Pourquoi n'y ai-je pas pensé? C'est exactement ce que je cherchais. Je vais essayer tout de suite. – Frank

+0

Existe-t-il une raison particulière d'utiliser 'arbitraire {}' au lieu de simplement '{}'? – Frank

+0

En ce qui concerne la structure étant spécifique. En fait, je voudrais autoriser 2-3 configurations d'arguments différentes, mais je devrais être capable de le trier en utilisant 'std :: is_invocable' – Frank