void-pointer
void-pointer

Reputation: 14827

Constexpr Variable Appears Uninitialized Inside Lambda

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;
}

Upvotes: 2

Views: 380

Answers (2)

void-pointer
void-pointer

Reputation: 14827

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.

Upvotes: 2

Seth Carnegie
Seth Carnegie

Reputation: 75130

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;
});

Upvotes: 0

Related Questions