9
votes

Comprendre STD :: En avant

Pourquoi le compilateur n'est pas capable de déduire le paramètre de modèle pour std :: Transférer code>?

Je veux dire: p>

#include <memory>
#include <iostream>

struct X{};

struct A{
    A( const X& ) { std::cout << "cpy ctor\n"; }
    A( X&& ) { std::cout << "move ctor\n"; }
};

X foo() { return {}; }

template<typename T,typename Arg>
T* factory( Arg&& a )
{
    return new T(std::forward(a));
    // ----------^^^^^^^^^^^^^^^ error: can't deduce template parameter
}

int main()
{
    factory<A>(foo());
}


3 commentaires

Pouvez-vous clarifier la question? Demandez-vous pourquoi la conception a été choisie pour prévenir la déduction de l'argument ou pourquoi la façon dont elle est mise en œuvre fonctionne pour prévenir la déduction?


Le point de spécifier le type manuellement est de sorte que transfert peut décider s'il doit être déplacer A ou non. Déduction de l'argument de modèle vous permet de déterminer le type de A mais pas si cela devrait être déplacé ou non.


@Angew le second.


3 Réponses :


12
votes

std :: Transférer est déclaré comme: xxx

typename std :: supprimer_reference :: Type est un contexte non déduit . Le compilateur n'a aucun moyen de savoir quel t doit être déduit car il ne comprend pas la connexion sémantique entre le type de membre type et un t . Il aurait besoin de rechercher tous les types pour trouver un match et être capable d'en quelque sorte des collisions de désambiguë. Ceci est déraisonnable, la norme ne le permet pas.


1 commentaires

Oui, c'est ce que je demandais. Je pense que lire Ce fera le reste.



9
votes

La raison pour laquelle vous devez spécifier un type pour Transférer code>, par conception, c'est ce qui arrive à a code> à l'intérieur de la fonction: xxx pré>

Étant donné que A code> est toujours em> un lvalue, il n'y a pas assez d'informations dans A code> pour pouvoir déterminer si elle a été transmise en tant que lvalue ou rvalue. que em> les informations sont uniquement disponibles via le type arg code>, qui sera soit x code> ou x & code>. Sans cette information de type supplémentaire, il est impossible de savoir si ou maintenant A code> doit être envoyé comme un lvalue ou une rvalue ... C'est pourquoi vous devez le fournir: P>

    return new T(std::forward<Arg>(a));
}


2 commentaires

Eh bien, je pensais que OP posait une question légèrement différente. Laissera cela ici quand même.


Oui, mon mauvais. Ce n'était pas très clair de la question. J'espère que la modification aide à comprendre ce qui était mon problème.



0
votes

de C ++ 11 Standard:

14.8.2.5 Arguments de modèle de déduction à partir d'un type

Les contextes non déduits sont:

- le spécificateur de nom imbriqué d'un type spécifié à l'aide d'un identifiant qualifié

- L'expression d'un spécificateur déclencheur.

- un argument de modèle de type de type ou une matrice liée dans laquelle a La subexpression fait référence à un paramètre de modèle.

- un paramètre de modèle utilisé dans le type de paramètre d'une fonction paramètre qui a un argument par défaut qui est utilisé dans l'appel pour quelle déduction de l'argument est en cours.

etc ...

std :: avance est déclaré comme ceci:

modèle Constexpr _TP && Transférer (Typename STD :: Remove_Reference <_TP> :: Type & __T) Noexcept

Selon la première phrase ci-dessus: typename std :: supprimer_reference <_tp> :: Type est un contexte non déduit.


0 commentaires