9

Literals are, in general, prvalues. Strings are a special case, defined as an array of char (meaning lvalue). This question is specifically about not string literals.

Why are non-string literals not const?

foo(42); // passes foo an `int`, not a `const int`.

You can't modify a non-string literal, so doesn't it make sense for it to be const?

Ivan Rubinson
  • 3,001
  • 4
  • 19
  • 48
  • Do you have in mind a use case where it would matter? – Angew is no longer proud of SO Aug 29 '18 at 12:18
  • 4
    Top-level const qualifiers on function arguments are discarded anyway (ie, `void foo(const int)` is identical to `void foo(int)`). So what difference would it make? – Useless Aug 29 '18 at 12:18
  • 4
    Not a duplicate - the title specifically excludes string literals, so a question about string literals literally cannot be a duplicate. – MSalters Aug 29 '18 at 12:19
  • I *really* can't think of a way for this to make a difference, except for literally writing `decltype(42)`. Can you elaborate on what it would bring? – Angew is no longer proud of SO Aug 29 '18 at 12:32
  • @Angew consider a template accepting a reference. https://stackoverflow.com/questions/52076660/template-accepts-const-but-not-literal/52076811#52076811 – Ivan Rubinson Aug 29 '18 at 12:53
  • 1
    Historical accident. In C, what you can and cannot modify was determined purely by the value category of the thing in question (lvalues are modifiable, rvalues are not), with a caveat that modifying a string literal (an lvalue) is UB, which is a typesystem wart. So when C++ tried to fix this, it added `const` to the type of string literals to make them statically non-modifiable. Other literals were statically non-modifiable to begin with, so no one felt there's a need to make them `const`. – n. m. could be an AI Aug 29 '18 at 13:00
  • @IvanRubinson I fail to see how this would help there, though. If the function accepts `T&`, it probably modifies its argument (otherwise it could accept `const T &`). Which means it would fail again for prvalues. – Angew is no longer proud of SO Aug 29 '18 at 16:13

2 Answers2

6

The literal answer is probably because literals predate the addition of const to the language, so naturally they are not const.

But the practical answer is - const prvalues are fundamentally strange things. You cannot create them from any of the fundamental types, but you can have a const prvalue of class type. But... why? Typically, we make things const to prevent further modifications right. But if it's a prvalue, it's not even a thing with identity - who is going to be there to observe its unintended modification? const prvalues prevent moving - because they're const, so you can't move from them, so its a premature pessimization.

Note that the one thing that could go wrong, that a hypothetical const literal would prevent, is already explicitly forbidden by the language:

void foo(int&);
foo(42); // error

But rather than making 42 const, the language made lvalue references non-const not allowed to bind to rvalues.

Barry
  • 286,269
  • 29
  • 621
  • 977
3

Remember that by default C++ is pass by value, meaning values are copied.

There's no way to modify a numeric literal value like 42, because all you have is a copy in a variable. The literal value itself doesn't even have to be stored in memory, the compiler could use it directly in the generated code.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • "There's no way to modify a numeric literal value" - So why isn't it `const`? – Ivan Rubinson Aug 29 '18 at 12:52
  • 1
    @IvanRubinson Because you can't do `42 = 5`? There's simply no need to make numeric literals constant since they by their very nature already are. Once you store a numeric literal in a variable, you have a ***copy*** of the numeric literal, a copy that you can modify as much as you want, because it's no longer the original literal value. – Some programmer dude Aug 29 '18 at 12:54
  • "There's no need to make numeric literals constant since they by their very nature already are" - That smells fishy. If it's `const` by its very nature, why isn't it `const`? – Ivan Rubinson Aug 29 '18 at 12:57
  • @IvanRubinson It seems you're not listening. For the last time, once you put a numeric literal value into a variable, it is the *variable* you work with, not the literal itself! A numeric literal is a [*prvalue*](http://en.cppreference.com/w/cpp/language/value_category#prvalue), they can *never* be on the left side of an assignment. You can't get the address of (pointer to) a numeric literal, there is no way in the language to modify one. – Some programmer dude Aug 29 '18 at 13:01
  • Literals have a type. An int literal has the type of int. If the literal can't be modified, why isn't its type const int (in addition to being a prvalue)? – Ivan Rubinson Aug 29 '18 at 13:07
  • 1
    @IvanRubinson - Because being a **pure rvalue** is enough. It's not an object, it's just a (nebulous) value that can be used to create an object. – StoryTeller - Unslander Monica Aug 29 '18 at 13:37