Когда статический член constexpr перестает быть constexpr? - PullRequest
0 голосов
/ 27 апреля 2018

У меня есть этот фрагмент.

#include <iostream>
#include <string>

struct JustStr {
    JustStr(const std::string& x) : val(x) {}
    static constexpr bool pred = false;
    std::string val;
};

template <typename T>
class C {
 private:
    T x;
 public:
    C(T x_) : x(x_) {}
    void f() {
        if constexpr (!x.pred) {
                std::cout << x.val << std::endl;
            }
    }

};

template<typename T>
void f2(T x) {
    T y(x);
    if constexpr (!y.pred) {
            std::cout << x.val << std::endl;
        }
}

int main() {
    C<JustStr> c(JustStr("yes"));
    c.f();  // Fails
    f2(JustStr("yes"));  // Succeeds
    return 0;
}

Мой вопрос: не должны ли c.f(); и f2(JustStr("yes")); терпеть неудачу или успешно одновременно? Почему один проваливается и почему другой преуспевает?

1 Ответ

0 голосов
/ 27 апреля 2018

Существует список вещей , которые не позволяют выражению считаться основным константным выражением.

Одна из вещей, которую вы не можете сделать, это оценить:

this, за исключением функции constexpr или конструктора constexpr, который оценивается как часть e;

В f() мы оцениваем this, чтобы увидеть, что такое x.pred (потому что на самом деле это this->x.pred), но f() не является функцией constexpr. Таким образом, этот пункт исключает c.f(). Если бы f() были constexpr, то это скомпилировалось бы.

В f2() мы нигде не оцениваем this, поэтому пул не применяется. Мы выполняем преобразование lvalue в rvalue, но оно ссылается на завершенный энергонезависимый объект const с предшествующей инициализацией, инициализированной константным выражением . Ничто другое не относится. Так что все в порядке.

...