constexpr Optional в С++17 не компилируется

template <typename T>
struct Optional {
    constexpr Optional() : has_value_{false} { }
    constexpr auto has_value() const -> bool { return has_value_; }

    union {
        T value;
    };
    
    bool has_value_;
};

static_assert(not Optional<int>{}.has_value());

Почему код не компилируется в C++17, но компилируется в C++20?

error: non-constant condition for static assertion


Ответы (1 шт):

Автор решения: Chorkov

gcc ругается более понятно:

<source>:13:15: error: non-constant condition for static assertion
   13 | static_assert(not Optional<int>{}.has_value());
      |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:13:15: error: 'constexpr Optional<T>::Optional() [with T = int]' called in a constant expression
<source>:3:15: note: 'constexpr Optional<T>::Optional() [with T = int]' is not usable as a 'constexpr' function because:
    3 |     constexpr Optional() : has_value_{false} { }
      |               ^~~~~~~~
<source>:3:15: error: 'constexpr' constructor for union 'Optional<int>::<unnamed union>' must initialize exactly one non-static data member
Compiler returned: 1

Т.е. проблема в том, что компилятор не смог вывести constexpr конструктор для union-а. Проблема решается явным указанием инициализирующего значения по умолчанию:

    union {
        T value = {};
    };

или

    constexpr Optional() : value{}, has_value_{false} { }

Кстати, зачем здесь union?

→ Ссылка