7
votes

Fonctions renvoyant des lvalues, renvoient toujours des références lvalue

Scott Meyers dans le point 3 du C ++ efficace dit

L'application de decltype à un nom donne le type déclaré pour ce nom. Les noms sont généralement des expressions lvalue, mais cela n'affecte pas le comportement de decltype. Pour les expressions lvalue plus compliquées que les noms, cependant, decltype garantit généralement que le type signalé est une référence lvalue. Autrement dit, si une expression lvalue autre qu'un nom a le type T, decltype signale ce type comme T &. Cela a rarement un impact, car le type de la plupart des expressions lvalue inclut intrinsèquement un qualificateur de référence lvalue. Les fonctions renvoyant des lvalues, par exemple, renvoient toujours des références lvalue.

Qu'est-ce que cela signifie quand il dit Les fonctions retournant des lvalues, par exemple, renvoient toujours des références lvalue

c++

7 commentaires

Pouvez-vous être plus précis et décrire quelle partie de cela n'a pas de sens pour vous? Je ne sais pas comment évaluer ce que vous faites ou ne comprenez pas à ce sujet. Quelles parties de cela comprenez-vous? Quelles parties de celui-ci vous laissent poser des questions? Et quelles sont les questions spécifiques que cela vous pose?


@Wyck Imho, ce que demande OP est assez clair. De plus, nous avons trois réponses et cinq votes positifs (un vote négatif) sur la question, ce qui impliquerait que les autres sont d'accord.


@dfrib Je ne suis pas d'accord. Pour être pédant, il n'est même pas clair d'après la question que le demandeur sait ce qu'est une fonction. C'est juste une citation et ensuite demander ce que cela signifie. Je pourrais coller n'importe quel passage de c ++ efficace et demander ce que cela signifie et attendre des votes positifs? Je crois que non.


@Wyck "Je pourrais coller n'importe quel passage de c ++ efficace et demander ce que cela signifie et attendre des votes positifs?" ; Je m'attendrais à ce que l'on s'attende à une réponse plutôt qu'à des votes positifs chaque fois que vous répondez à une question, mais les votes positifs pour une question particulière indiquent quelque chose sur la façon dont elle est perçue par la communauté. En regardant le quota de vote à la hausse / à la baisse pour celui-ci, il est apparemment bien perçu, et le paragraphe cité en particulier est en outre sans doute autonome. Un paragraphe aléatoire d'un livre d'étude n'est pas nécessairement ni autonome ni matériel pour une question valide. Imho, c'est un cependant.


@Wyck C'est très clair pour beaucoup d'entre nous; si vous ne comprenez pas, même après avoir lu les réponses, vous pouvez simplement passer à une question plus appropriée. :)


@AsteroidsWithWings moi?!? Cela n'a rien à voir avec moi. C'est quelqu'un qui a posé une question de la forme: Qu'est-ce que tu veux dire quand tu dis: "passage du livre" . Sans fournir de contexte supplémentaire. Bien que ce soit un bon talon pour un wiki de communauté, cela ne permet pas de clarifier les malentendus. Je donne, à titre de preuve, que la réponse positive commence par "Cela signifie ce qu'elle dit". C'est une réponse tautologique qui met en évidence l'aspect de la question qui était pauvre. La viande du passage n'a pas d'importance. Il s'agit de savoir comment demander.


@Wyck Personne d'autre n'a de problème avec ça. Il est temps de passer à autre chose...


3 Réponses :


3
votes

Cela signifie ce qu'il dit!

Il n'y a aucun moyen de créer une fonction, de sorte que son type de retour ne soit pas T& , mais son appel aboutit à une expression lvalue.

Tous les autres types de retour font que l'appel de fonction est une expression rvalue.

C'est intuitif quand on considère que la seule façon de "renvoyer" quelque chose qui existe déjà est par référence - le résultat d'un appel de fonction est par ailleurs toujours un "temporaire", que ce soit parce qu'il copie une variable locale, ou parce qu'il se déplace de une variable locale.

L'exception potentielle à cette règle, renvoyant T&& , ne s'applique pas non plus car elles produisent des expressions rvalue (ce qui fait fonctionner la sémantique de déplacement, puisque seules les expressions rvalue peuvent continuer à se lier aux paramètres T&& ).

Scott rapporte une conséquence des règles du langage, et nous dit que la même conséquence a été utilisée pour justifier l'une des règles de decltype .

On peut soutenir qu'il aurait pu le formuler plus clairement ainsi:

Les seules fonctions dont les appels évaluent à lvalues sont celles qui renvoient des références à lvalue.


2 commentaires

Il existe un moyen: en using function_type = void(); function_type&& f(); , le type de retour de la fonction est une référence rvalue, mais f() est une lvalue


@Artyer "le type de retour de la fonction est une référence rvalue" Non pas vraiment.



0
votes

Tout d'abord, nous n'avons aucune difficulté à trouver un exemple d'expression lvalue qui est aussi un nom:

#include <type_traits>

int f() { return 42; };
int& g() { static int g_x; return g_x; }

int main() {
    int x;
    int arr[3] = {1, 2, 3};

    static_assert(
        std::is_same_v<decltype(x), int>, "");
    //                          ^ - 'x' is a name, and an lvalue

    static_assert(
        std::is_same_v<decltype(arr[1]), int&>, "");
    //                          ^^^^^^ - 'arr[1]' is an lvalue expression
    
    static_assert(
        std::is_same_v<decltype((x)), int&>, "");
    //                          ^^^ - '(x)' is an lvalue expression
    
        static_assert(
        std::is_same_v<decltype(f()), int>, "");
    //                          ^^^ - 'f()' is not an lvalue
    
            static_assert(
        std::is_same_v<decltype(g()), int&>, "");
    //                          ^^^ - 'g()' returns an lvalue
}

Mais qu'est-ce qu'une lvalue qui n'est pas un nom?

Par exemple, considérez

int f() {}

Un appel de f() ici n'est pas une expression lvalue. Il n'y a en fait pas trop de choses qui ne sont pas des noms mais qui sont des expressions lvalue, et Scott désigne simplement pour toutes celles qui sont réellement des expressions lvalues mais pas des noms, le type correspondant signalé par decltype est de type référence lvalue, par conception.

int x{42};
x;  // 'x' here is a name and an lvalue expression


0 commentaires

0
votes

Donné:

error: variable ‘foo<int&> x’ has initializer but incomplete type
 foo<decltype(*(int*)0)> x{};
                         ^
error: variable ‘foo<int> y’ has initializer but incomplete type
 foo<decltype(v)> y{};
                  ^

Vous obtenez:

template<typename T> struct foo;
foo<decltype(*(int*)0)> x{};
int v;
foo<decltype(v)> y{};

Comme vous pouvez le voir, decltype donne int& pour le pointeur déréférencé, mais seulement int pour la variable int v .

Pour les fonctions, il veut dire que la seule façon pour elles de renvoyer une lvalue est de renvoyer une référence lvalue.


0 commentaires