Неопределенная ссылка на статический член constexpr, используемый только значением - PullRequest
2 голосов
/ 25 марта 2019

Я пытался создать умный класс, содержащий стиль шрифта.Раньше это состояло из 3 перечислений с побитовыми совместимыми значениями (каждый набор значений не имел перекрывающихся битов с другими перечислениями), поэтому вы могли сделать FontStyle::LEFT | FontStyle::TOP

Но Clang предупредил меня о комбинировании несвязанных перечислений и даЯ видел возможные ошибки здесь: FontStyle::LEFT | FontStyle::RIGHT установил оба бита.Поэтому я переработал класс, используя вспомогательный класс для предыдущих перечислений и шаблонов, чтобы они соответствовали правильным значениям.Но теперь я получаю ошибки компоновщика для clang в сборках Debug с undefined reference для моих static constexpr участников.

Просмотр Неопределенная ошибка ссылки для статического члена constexpr предполагает, что значениеиспользуется ODR, но я не использую никаких ссылок.

Когда статическому члену класса constexpr требуется определение вне класса? это затем указало мне на неявную копиюконструктор моего вспомогательного класса, который является проблемой.

Есть ли шанс, что я смогу избежать внеклассных определений в C ++ 14 (C ++ 17 уже позволяет их опускать) и отладочных сборках (Ctors оптимизированы в Release, и, следовательно, нет неопределенных ссылок)?

Связанный код :

#include <array>
#include <cstdint>

namespace detail {
template<unsigned T_index>
struct FontStylePart
{
    constexpr FontStylePart(uint8_t val) : value(val) {}
    uint8_t value;
};
} // namespace detail

class FontStyle
{
    static constexpr unsigned AlignH = 0;
    static constexpr unsigned AlignV = 1;

public:
    constexpr FontStyle() = default;

    template<unsigned T_index>
    constexpr FontStyle(detail::FontStylePart<T_index> style) : FontStyle()
    {
        value[T_index] = style.value;
    }

    /// Horizontal align
    static constexpr detail::FontStylePart<AlignH> LEFT = 0;
    static constexpr detail::FontStylePart<AlignH> RIGHT = 1;
    static constexpr detail::FontStylePart<AlignH> CENTER = 2;

    /// Vertical align
    static constexpr detail::FontStylePart<AlignV> TOP = 0;
    static constexpr detail::FontStylePart<AlignV> BOTTOM = 1;
    static constexpr detail::FontStylePart<AlignV> VCENTER = 2;

private:

    std::array<uint8_t, 3> value = {{0, 0, 0}};
};

int main() {
  FontStyle style = FontStyle::CENTER;
  return 0;
}

1 Ответ

0 голосов
/ 25 марта 2019

Линия

FontStyle style = FontStyle::CENTER;

- это использование ODR FontStyle::CENTER.

Я пытался использовать

constexpr FontStyle style = FontStyle::CENTER;

но я столкнулся с проблемами в конструкторе. Следующее работает, хотя мне не ясно, приемлемо ли это для ваших нужд.

int main() {
   constexpr auto v = FontStyle::CENTER;
   FontStyle style = v;
   return 0;
}

Это переносит ответственность за использование ODR на constexpr auto v.

...