3

I have the following code

constexpr int into(int a,int b)
{
  int c=a*b;
  return c;
}

int main()
{
 constexpr int &n=into(5,5);

}

and I have read (in MSDN)

The keyword constexpr was introduced in C++11 and improved in C++14. It means constant expression. Like const, it can be applied to variables so that a compiler error will be raised if any code attempts to modify the value.

After I read it, I thought that constexpr can be used in place of const, but for the above code I get a compiler error stating

`int main()':
invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'`

When constexpr is replaced with const, it works fine. I don't understand this behavior; can somebody shed some light?

T.C.
  • 133,968
  • 17
  • 288
  • 421
RaGa__M
  • 2,550
  • 1
  • 23
  • 44
  • 1
    A `constexpr` reference has to bind to a global variable. See answer [here](http://stackoverflow.com/a/28614655/1460794). – wally May 03 '16 at 12:23
  • @flatmouse,thanks for the replay... one of the answer in the link says "A reference is conceptually equivalent to taking the address of the variable, and the address of a local variable is not a constant" here when i use const it binds. but not only to the constexpr.i believe the behavior of const and constexpr to a variable is same – RaGa__M May 03 '16 at 12:35
  • The problem might be that the return value of `into` is not saved anywhere, but you do save a reference to that return value, so where does that reference have to point to? – Oebele May 03 '16 at 12:43
  • Has it needs to be saved? has the function call don't save the result anywhere temporarily, has compiler RVO comes into play? – RaGa__M May 03 '16 at 12:50

2 Answers2

6

Unlike const, which applies to int, the constexpr keyword applies const directly to the variable of reference type int&, which has no effect.

typedef int &int_ref;

int main() {
    int x = 1;
    int &a = x;          // OK
    int_ref b = x;       // OK, int_ref is 'int &'
    const int &c = 1;    // OK, reference to const int
    const int_ref d = 1; // error: type of d is 'int &'
                         // qualifier on reference are being ignored
}

constexpr int &n and constexpr int_ref n is the same, while const int &n and const int_ref n have the qualifier different.

user1887915
  • 1,299
  • 10
  • 13
3

Expressions marked as constexpr will be resolved at compile-time, which will treat the result of into(5,5) as an int literal. As we know, references cannot be bound to an int literal in C++.

You could make this work by making constexpr int x=into(5,5); appear at the global scope and within the main creating a constexpr const int reference to x forcing x to be resolved before main is called which then allows a reference to be bound to x:

constexpr int into(int a,int b) {
  int c=a*b;
  return c;
}

// guaranteed to be resolved before main is called
constexpr int x = into(5,5);

int main() {
 constexpr const int& n = x;
 static_assert(n == 25, "whoops!");
}

To specifically answer your question, this is completely orthogonal to rvalues or move semantics, but rather is a nuance of constexpr.

If global scoping gives you heartburn, you could make x a static as well and put its initialization before its reference binding, which seems more natural to me:

constexpr int into(int a,int b) {
  int c=a*b;
  return c;
}  

int main() {
 // guaranteed to be resolved before main is called
 static constexpr int x = into(5,5);
 constexpr const int& n = x;
 static_assert(n == 25, "whoops!");
}
erip
  • 16,374
  • 11
  • 66
  • 121
  • 1
    "*As we know, references cannot be bound to an int literal in C++."*, what references do you mean? – Piotr Skotnicki May 03 '16 at 13:02
  • 1
    @erip,things not clear you said 'into(5,5) as an int literal. As we know, references cannot be bound to an int literal in C++.' i believe calling the into() function return int&& which is an rvalue and it should be assigned to constant reference, things went fine when i put const int &n=into(5,5); inside main..if const can why can't the constexpr was the constexpr is missing something to deal with this case – RaGa__M May 03 '16 at 13:04
  • @PiotrSkotnicki I mean references to `int` literals. :) `int& x = 25;` is not legal. You can certainly have `const` references to `int` literals, but that's different from the resolution of `constexpr` as I understand it. – erip May 03 '16 at 13:04
  • @RichardGeorge `into` is going to return what you mark it to return. In this case, it's an `int` (which is what you want lest you feel the wrath of dangling references). – erip May 03 '16 at 13:05
  • 1
    @erip then according to your reasoning it should be possible to write `constexpr const int&` – Piotr Skotnicki May 03 '16 at 13:07
  • @PiotrSkotnicki There is still the problem of resolution times. It's quite legal to have `static constexpr const int& n = into(5,5);` because it's guaranteed to be resolved by the time `main` is invoked. – erip May 03 '16 at 13:08
  • @PiotrSkotnicki If you feel I'm not explaining it well, I invite you to downvote and provide an answer. :) – erip May 03 '16 at 13:11
  • 1
    @RichardGeorge Clarification: You are wrong in your assumption that `const` and `constexpr` are the same. `constexpr` means "known at compile time", `const` means "cannot be changed after per-iteration assignment". `const int i& = n;` assigns i to whatever n is this time round, but we cannot modify through i. `constexpr i = 25` means that `i` can be elided and 25 substituted in its place during compilation. – kfsone May 03 '16 at 16:29
  • @kfsone, its not my assumption ,it was what I read, if you look at the block I pasted from MSDN "The keyword constexpr was introduced in C++11 and improved in C++14. It means constant expression. Like const, it can be applied to variables so that a compiler error will be raised if any code attempts to modify the value." – RaGa__M May 04 '16 at 05:11