emplace_back вызывает ошибку ссылки на статическом элементе constexpr - PullRequest
0 голосов
/ 27 мая 2018

Почему emplace_back принимает ссылку на член, который требует определения?В чем разница между emplace_back(integer literal) и emplace_back(static constexpr integer member)?

Если я переключаюсь на C ++ 17, он компилируется нормально.Я обнаружил, что в C ++ 17 статические члены данных constexpr неявно встроены .Означает ли это, что компилятор неявно создает для них определение?

Пример кода:

class base {
    int n;
public:
    base(int n):n(n) {}
};

struct base_trait {
    static constexpr int n = 1;
};

int main(void) {
    vector<base> v;
    v.emplace_back(1);  // ok
    v.emplace_back(base_trait::n);  // link error with -std=c++14, ok with -std=c++17
    return 0;
}

1 Ответ

0 голосов
/ 27 мая 2018

Как вы сказали, emplace_back принимает аргументы по ссылке, поэтому передача base_trait::n приводит к тому, что используется odr .

объект используется odr, если его значение читается (если это не постоянная времени компиляции) или записывается, его адрес берется или ссылка на него привязывается;

До C ++ 17 это означает, что здесь требуется определение base_trait::n.Но, начиная с C ++ 17, поведение изменилось, для член статических данных constexpr определение вне класса снова не требуется.

Если const non-inline (since C++17) статические данныеэлемент or a constexpr static data member (since C++11) используется odr, определение в области именного пространства все еще требуется, но не может иметь инициализатора.This definition is deprecated for constexpr data members (since C++17).

Статический элемент данных может быть объявлен встроенным.Встроенный статический член данных может быть определен в определении класса и может указывать инициализатор.Это не нуждается во внеклассном определении.(начиная с C ++ 17)

...