Конструктор использует функцию, принимающую ссылку и возвращающую значение, при многократном изменении члена данных:
constexpr int vv(int x) {return x;}
constexpr int & rr(int & x) {return x;}
constexpr int rv(int & x) {return x;}
constexpr struct S {
int x {0};
template<typename F> constexpr S(F f) {x = f(x) + 1; x = f(x) + 1;}
} s(rv); // s.x is 1 if function rv is used, 2 otherwise.
static_assert(s.x == 2, "");
Только функция rv
дает неожиданный результат при использовании в конструкторе. Если вместо vv
или rr
передается s.x
2, как ожидалось.
Я заметил поведение в GCC 5.4.1 ARM и, похоже, во всех версиях GCC, поддерживающих С++ 14, одинаково. Во всех случаях Clang дает ожидаемый результат 2. Ни GCC, ни Clang не дают никаких предупреждений о включении Wall и Wextra.
Является ли этот пример допустимым С++ 14 и ошибкой в GCC? Я прочитал список ограничений на постоянные выражения в стандарте и не вижу ничего очевидного, что это нарушает, но я не уверен, что понимаю все технические детали.