zmienna constexpr nie została przechwycona

Dec 10 2020

Poniższy kod nie kompiluje się w clang (tak jest w GCC):

struct A{
    int a;
};

auto test(){
    constexpr A x{10};
    return []{
        return x; // <-- here x is A: clang doesn't compile
    }();
}

Błąd Clanga polega na tym, że zmienna „x” nie może być niejawnie przechwytywana w lambdzie bez określonej wartości domyślnej przechwytywania , ale myślałem, że zmienne constexpr są zawsze przechwytywane.

Jeśli x jest liczbą int, kod kompiluje się:

auto test(){
    constexpr int x{10};
    return []{
        return x; // <-- here x is int: clang is ok
    }();
}

Co ciekawe, kompiluje się również poniższy kod:

auto test(){
    constexpr A x{10};
    return []{
        return x.a;
    }();
}

Czy clang jest w porządku? Jeśli tak, jakie jest tego uzasadnienie? Używam -std = c ++ 17

--EDYTOWAĆ--

Następujące pytanie: czy mogę użyć wartości constexpr w lambdzie bez przechwytywania jej? nie ma związku z tym, ponieważ z clang11 nie stanowi już problemu: w rzeczywistości, jak wspomniano powyżej, jeśli x jest int, kompiluje się clang11.

Przykładowy kod obecny również w https://godbolt.org/z/rxcYjz

Odpowiedzi

2 DavisHerring Dec 25 2020 at 07:09

W return x;pierwszym przykładzie musisz wywołać Akonstruktor kopiujący, który wiąże się z odwołaniem się do niego, xa tym samym używa go odr. Można argumentować, że trywialna kopia wartości użytecznej w stałych wyrażeniach nie powinna stanowić więcej niż użycie odr return x.a;, ale nie ma takiego wyjątku w tej regule, więc Clang słusznie ją odrzucił.

Ze względów praktycznych możesz oczywiście utworzyć dowolną constexprzmienną, staticaby uniknąć konieczności jej przechwytywania.