2

In the code sample below, I would expect the output to be as follows, since x is a static constexpr variable.

5
5
5
5

However, g++ warns me that x is uninitialized inside the lambda function when I compile with -Wall, and the last three lines of the output vary, presumably because the value of uninitialized memory on the stack is being printed. Here is one possible output produced by the program when it is compiled with the options -Wall -std=c++0x. Why is the output not what I expect it to be?

5
32718
32718
32718

If it helps, the expected output is produced when constexpr is deleted in the declaration constexpr T x.

Example Program

#include <algorithm>
#include <iostream>

struct _foo
{
        template <class T>
        struct traits
        {
                static constexpr T val = 5;
        };

        template <class T>
        constexpr T getval() const { return traits<T>::val; }
} foo;

struct _test
{
        template <class T>
        void bar(const T& t)
        {
                int arr[] = { 1, 2, 3 };
                constexpr T x = foo.getval<T>();
                std::cout << x << std::endl;
                std::for_each(arr, arr + 3, [&](int i) {
                        std::cout << x << std::endl;
                });
        }
} test;

int main()
{
        test.bar(5u);
        return 0;
}
1
  • Note: Leading underscores are reserved in global scope, so technically this code has undefined behavior. Commented Apr 20, 2016 at 23:27

2 Answers 2

2

This was indeed a compiler bug. I reported it here, and it was confirmed a while ago. It doesn't crash on older versions of g++, because the constexpr keyword is just parsed and ignored.

Sign up to request clarification or add additional context in comments.

Comments

0

You have to capture x in the lambda's capture list:

std::for_each(arr, arr + 3, [&](int i) { // notice the & (capture the outside env
                                         // by reference
    std::cout << x << std::endl;
});

5 Comments

I just added that as you posted this answer. Same problem.
I'm using g++ 4.6.1 on Linux Mint 64-bit. Also, the fact that it's not reported as an error without the ref-capture may be another compiler bug.
Apparently g++ 4.5 doesn't support constexpr; it merely parses and ignores it. gcc.gnu.org/bugzilla/show_bug.cgi?id=51604
I submitted a bug report here for g++ 4.6.1: gcc.gnu.org/bugzilla/show_bug.cgi?id=52026.
You don't need to capture x, because it is not ODR-used by the lambda, because it satisfies the requirements for appearing in a constant expression and the lvalue-to-rvalue conversion is immediately applied. See [basic.def.odr]p2.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.