À l'égard des autres réponses: Nous sommes traitant explicitement de n3638 ici, et comment il est intégré dans la récente projets de C++1y.
Je suis en utilisant 9514cc28 du comité de dépôt github, qui intègre certains (mineur) des corrections/modifications n3638 déjà.
n3638 permet explicitement:
struct A {
auto f(); // forward declaration
};
auto A::f() { return 42; }
Et, comme on peut l'inférer à partir de [dcl.spec.auto], où cette fonction est spécifiée, même les éléments suivants seront juridiques:
struct A {
auto f(); // forward declaration
};
A x;
auto A::f() { return 42; }
int main() { x.f(); }
(mais plus sur cela plus tard)
C'est fondamentalement différente de toute fuite-retour-type ou dépendantes à la recherche d'un nom, comme auto f();
est une déclaration préliminaire, semblable à de la struct A;
. Il doit être rempli plus tard, avant de l'utiliser (avant le type de retour est requis).
De plus, les problèmes dans les OP sont liées à l'intérieur d'erreurs du compilateur. La récente clang++3.4 tronc 192325 Debug+Affirme l'échec de la construction de compiler comme une assertion échoue lors de l'analyse de la ligne, return L.b_ == R.b_;
. Je n'ai pas vérifié avec une version récente de g++ à partir de maintenant.
Est le cas des OP exemple juridique wrt pour un n3638?
C'est un peu délicat de l'OMI. (Je suis toujours en se référant à 9514cc28 dans cette section.)
1. Où est-il autorisé à utiliser "auto"?
[dcl.spec.auto]
6 Un programme qui utilise auto
ou decltype(auto)
dans un contexte non explicitement autorisés dans cette section est mal formé.
2 L'espace réservé type peuvent apparaître avec une fonction de demande de déclaration dans le decl-spécificateur-seq, type spécificateur-seq, conversion en fonction de l'id, ou de fuite-de retour, dans un contexte où une telle déclaration est valide.
/5 définit également certains contextes, mais ils sont hors de propos ici.
Par conséquent, auto func()
et auto operator@(..)
sont généralement autorisés (ce qui suit à partir de la composition d'une déclaration de fonction en tant que T D
où T
est de la forme decl-spécificateur-seq, et auto
est un type spécificateur).
2. Est-il permis d'écrire " auto func();`, c'est à dire une déclaration qui n'est pas une définition?
[dcl.spec.auto]/1 dit
L' auto
et decltype(auto)
type de spécificateurs de désigner un espace réservé à un type qui sera remplacé plus tard, soit par déduction à partir d'un initialiseur ou par spécification explicite avec une fuite de retour.
et /2
Si la déclaration de type de retour de la fonction contient un espace réservé à un type, le type de retour de la fonction est déduite de l' return
des déclarations dans le corps de la fonction, le cas échéant.
Bien qu'il n'est pas explicitement autoriser une déclaration telle que celle - auto f();
pour une fonction (qui est, une déclaration sans définition), il est clair à partir de n3638 et [dcl.spec.auto]/11 qu'il est destiné à être autorisé, et pas explicitement interdit.
3. Qu'en est ami de fonctions?
Jusqu'à présent, l'exemple
struct A
{
int a_;
friend auto operator==(A const& L, A const& R);
}
auto operator==(A const& L, A const& R)
{ return L.a_ == R.a_; }
doit être bien formé. La partie intéressante est maintenant la définition de l'ami de la fonction à l'intérieur de la définition de l' A
, qui est
struct A
{
int a_;
friend auto operator==(A const& L, A const& R)
{ return L.a_ == R.a_; } // allowed?
}
À mon avis, c'est permis. Pour ce faire, je vais citer la recherche d'un nom. La recherche de nom à l'intérieur de la définition des fonctions définies dans un ami de la déclaration de la fonction suit la recherche par nom de membre de fonctions comme par [de base.de recherche.unqual]/9. /8 du même article spécifie non qualifiés de recherche pour les noms utilisés à l'intérieur de membres de la fonction des organes. L'une des façons un nom peut être déclaré pour être utilisé, c'est qu'il "doit être un membre de la classe X
, ou être membre d'une classe de base de l' X
(10.2)". Ceci permet de largement connu
struct X
{
void foo() { m = 42; }
int m;
};
Notez comment m
n'est pas déclarée avant son utilisation en foo
, mais c'est un membre de l' X
.
À partir de cela, je conclus que, même
struct X
{
auto foo() { return m; }
int m;
}
est autorisée. C'est pris en charge par clang++3.4 tronc 192325.
Recherche de nom nécessite d'interpréter cette fonction uniquement après l' struct
a été terminé, pensez également à:
struct X
{
auto foo() { return X(); }
X() = delete;
};
De même, le corps de l'ami des fonctions définies à l'intérieur d'une classe ne peuvent être interprétées qu'une fois que la classe est terminée.
4. Que sur les modèles?
Plus précisément, qu'en friend auto some_function(B const& L) { return L.b_; }
?
Tout d'abord, le injecté-classe nom- B
est équivalent à B<T>
, voir [temp.local]/1. Il se réfère au courant de l'instanciation ([temp.dep.type]/1).
L' id de l'expression- L.b_
se réfère à un membre de l'actuel de l'instanciation (/4). Il est également dépendante des membres de l'actuel instanciation -- c'est une addition faite après C++11, voir DR1471, et je ne sais pas quoi penser à ce sujet: [temp.dep.expr]/5 membres de cette id-expression n'est pas dépendant du type, et aussi loin que je vois [temp.dep.constexpr] ne veut pas dire que c'est la valeur-dépendante.
Si le nom en L.b_
n'était pas dépendante, la recherche d'un nom suivra les "habituels de la recherche du nom de" règles par [temp.nondep]. Le reste, ça va être fun (dépendant de recherche de nom n'est pas très bien indiqué), mais considérant que
template<class T>
struct A
{
int foo() { return m; }
int m;
};
est acceptée par la plupart des compilateurs ainsi, je pense que la version avec auto
devrait être valide, trop.
Il y a aussi une section sur les amis de modèles dans [temp.ami], mais IMO il n'est pas jeter de la lumière sur la recherche de nom ici.
Voir aussi cette discussion dans le isocpp-forum.