повысить static_vector не std :: is_trivially_destructible - PullRequest
4 голосов
/ 19 марта 2019

Согласно этому примеру (левый пример)

#include <array>
#include <boost/container/static_vector.hpp>

struct X {
  int k;
  std::array<int, 4>                      a;
  boost::container::static_vector<int, 4> b;
  ~X() = default;
};

int huh()
{
  std::array<X, 5> x;
  return 0;
}

похоже, что boost::container::static_vector<T, N> является тривиально разрушаемым, когда T (циклический цикл b не происходиткогда X уничтожается).huh оптимизируется до xor eax, eax; ret (то есть return 0 без зацикливания массива.

Когда я использую вместо этого содержащийся тип, который имеет нетривиальный деструктор (правый пример)

#include <array>
#include <boost/container/static_vector.hpp>

struct Y {
  ~Y();
};

struct X {
  int k;
  std::array<int, 4> a;
  boost::container::static_vector<Y, 4> b;
  ~X() = default;
};

int huh()
{
  std::array<X, 5> x;
  return 0;
}

происходит цикл

    add     rbx, 1
    call    Y::~Y() [complete object destructor]
    cmp     rbx, r12
    jne     .L3

Я думаю, что это имеет смысл до сих пор. Память, занятая static_vector с тривиально разрушаемым объектом, может быть просто освобождена в постоянное время, независимо от того, сколько объектов на самом делесохранено.

Что меня удивляет, так это то, что значение std::is_trivially_destructible<boost::container::static_vector<int, 4> >::value равно false. Это просто неверная черта типа?

Ответы [ 2 ]

3 голосов
/ 19 марта 2019

boost::container::static_vector<X, N> является производным от класса boost::container::vector<X, ...>, который имеет некоторый определенный конструктор.Даже если все его тело исключено компилятором в выпуске, класс уже не тривиально разрушаем:

struct X
{
};

struct Y
{
    ~Y() = default;
};

struct Z
{
    ~Z() {};
};

static_assert(std::is_trivially_destructible<X>::value, ""); // Succeeds
static_assert(std::is_trivially_destructible<Y>::value, ""); // Succeeds
static_assert(std::is_trivially_destructible<Z>::value, ""); // Fails

Это техническая причина, по которой он отсутствует в текущей реализации Boost.Может ли быть другая реализация, где std::is_trivially_destructible<boost::container::static_vector<int, 4> >::value верно?Да, это возможно, но я предполагаю, что требуется специализация boost::container::static_vector для тривиально разрушаемых типов.

1 голос
/ 19 марта 2019

boost::static_vector наследуется от boost::vector: https://github.com/boostorg/container/blob/develop/include/boost/container/static_vector.hpp#L106. Поскольку boost::~vector() нетривиально, то есть boost::vector, а также boost::static_vector.


Обратите внимание, что ваши рассуждения неверны. Во втором случае вызовы деструктора не могут быть оптимизированы, так как компилятор не видит его определения. Попробуйте изменить Y(); на ~Y() { }. Простая демонстрация: https://godbolt.org/z/pg2xS4.

Почему нельзя разрешить компиляторам оптимизировать нетривиальные вызовы деструкторов, если они не имеют наблюдаемых эффектов?

...