3

I'm not sure if I'm missing something, but, user-defined literals, which invokes user-defined functions that could return anything, are also a kind of literals.

The standard says that a literal is always a prvalue, unless it is a string literal, but:

#include <iostream>
#include <typeinfo>

int& operator""_a(unsigned long long c);

int main()
{
    std::cout << std::is_same<decltype(5_a), int&>::value;
} 

prints 1 in both GCC and Clang, which proofs that the literal 5_a (which is not a string literal) is being treated as a lvalue instead of an rvalue:

[expr.prim.literal]/1 A literal is a primary expression. Its type depends on its form. A string literal is an lvalue; all other literals are prvalues.

and user-defined literals are literals too.

What is what I'm missing?

ABu
  • 10,423
  • 6
  • 52
  • 103
  • According to [this value category reference](http://en.cppreference.com/w/cpp/language/value_category) lvalues include "a function call or an overloaded operator expression, whose return type is lvalue reference". What user-defined literals really are, are overloaded operators (in the case of your example, `5_a` is equal to the call `operator""_a(5)`). And your operator function returns an lvalue reference, which you compare to an lvalue reference of the same type. – Some programmer dude Oct 02 '17 at 14:48
  • @Someprogrammerdude but it is also a literal. It is, besides, written in *italics*, to emphatice that it refers to all the constructors under the *literal* syntax rule, and I would say a standard cannot contain contradictions. – ABu Oct 02 '17 at 14:56
  • 5
    @Peregring-lk A standard is a document written by humans. What do you mean it cannot contain contradictions? It *should* not, using standards definitions it *must* not, but it probably does anyway and this may be one of them. – Daniel H Oct 02 '17 at 14:57
  • @DanielH Yes of course. I don't meant I'm demanding it must be correct, but to express that the solution must be either it is a defect of the standard or a defect in my reading, because a standard wants to be a "contradictory"-free document. Maybe in my mother language "cannot" is less restrictive in informal speech than in english. – ABu Oct 02 '17 at 15:06
  • 3
    Not putting this as an answer as I'm not 100% sure but I think [this](https://timsong-cpp.github.io/cppwp/n4659/over.literal#7) is the reason why you are not seeing it is a prvalue. – NathanOliver Oct 02 '17 at 15:08
  • @NathanOliver I already read that but it's a note (non-normative), and it says that is constrained by the previous bullets (whose, by context, makes it a literal), and thus [expr.prim.literal]/1 still applies. – ABu Oct 02 '17 at 15:16
  • 2
    The note may not be normative. But it leads to [lex.ext]/[2](https://timsong-cpp.github.io/cppwp/n4659/lex.ext#2). And that *is* normative – StoryTeller - Unslander Monica Oct 02 '17 at 15:45
  • 1
    Obvious standard wording defect is obvious. Does this actually matter? Yes, `5_a` is an lvalue in your example, and presumably all compilers correctly invoke it as such. Is there a real source of confusion? – Barry Oct 02 '17 at 15:50
  • @Barry No, but you cannot then theoretically resort on user-defined literals returning references of any kind. – ABu Oct 02 '17 at 15:52
  • @Peregring-lk Who can't? Your question states that gcc and clang both interpret that expression as an lvalue. – Barry Oct 02 '17 at 15:55
  • @Barry can I deduce by your words that the correct reading of the standard is the common output between Clang and GCC instead of the standard itself? – ABu Oct 02 '17 at 16:07
  • @Barry I know that this specific question is not a very important one, but moving the solution to compiler outputs I think is not a way of addressing contradictions, even if they are not polemic. I knew beforehand that the output should be an lvalue; I just ask the question because reading that made me to not be sure, because sometimes things that seems obvious aren't, like that `using T = decltype([]{}); T t;` is ill-formed while `template void f(T const&) { T t; t(); }; f([]{});` isn't. – ABu Oct 02 '17 at 16:08

1 Answers1

4

Yes, this is a minor wording defect in the standard. You can find that sentence (nearly) unchanged all the way back in N1905:

A literal is a primary expression. Its type depends on its form (2.13). A string literal is an lvalue; all other literals are rvalues.

This standard predates user-defined literals by a few years (N2765 is from mid-2008), and this particular wording wasn't change to reflect that the "all other literals are [p]rvalues" part shouldn't include user-defined literals.

However, it's pretty clear that since a user-defined-literal is simply syntax sugar for a function call, its value category should be derived from the function call as well. That's the point of the language feature. There's no confusion that the value category of 5_a in your example is lvalue and not prvalue (all compilers agree), so a defect report for this wording would get pretty low precedence, if any.

Barry
  • 286,269
  • 29
  • 621
  • 977