Поиск чего-то подобного offsetof () для типов не-POD

Что ж, вместо того, чтобы вручную выбирать вишню, вы можете автоматически выбирать вишню, то есть перебазировать:

git rebase A B

git автоматически:

  • выяснит родительский коммит между A и B
  • проходят через все коммиты в B, которые будут применены поверх A
  • выясняют, что некоторые коммиты уже находятся в A и их не нужно применять снова.

Однако, вы можете столкнуться с множеством конфликтов на этом пути.

Я полагаю, что если для вас импортируется чистая история на момент слияния, вы настраиваете свой рабочий процесс так, чтобы иметь git rebase origin/A вместо git merge origin/A, что означает, что ваша история останется чистой. Вы также можете немного прочитать о рабочих процессах git rebase.

9
задан yungchin 7 October 2008 в 12:36
поделиться

6 ответов

В зависимости от того, как портативный Вы хотите быть, можно использовать offsetof () даже на типах не-POD. Это не строго совместимо, но в пути offsetof () реализован на gcc и MSVC, это будет работать с типами не-POD в текущей версии и недалеком прошлом.

4
ответ дан 3 November 2019 в 00:05
поделиться

Решение Greg Hewgill, вероятно, предпочтительно для этого (возможно, с составом, а не наследованием).

Однако я думаю, что с GCC на x86 и x86_64, offsetof будет на самом деле работать даже на членов типов не-POD, пока он "имеет смысл". Так, например, это не будет работать на участников, наследованных от виртуальных базовых классов, потому что в GCC это реализовано с дополнительной косвенностью. Но, пока Вы придерживаетесь простого общедоступного единичного наследования, GCC именно так, оказывается, размечает Ваши объекты способом, что означает, что каждый участник доступен при смещении от объектного указателя, таким образом, offsetof реализация даст правильный ответ.

Проблема с этим, конечно, состоит в том, что необходимо проигнорировать предупреждения, что означает, делаете ли Вы что-то, что не работает, Вы разыменуете указатель близко к пустому указателю. Зато, причина проблемы, вероятно, будет очевидна во времени выполнения. На минус сторона, eeew.

[Редактирование: я только что протестировал это на gcc 3.4.4, и на самом деле предупреждение обновлено до ошибки при получении смещения участника, наследованного от виртуального базового класса. Который хорош. Я все еще немного волновался бы, что будущая версия gcc (4, даже, который я не должен вручать) будет более строгой, и это, если Вы проявите этот подход Ваш май кода в будущей компиляции остановки.]

5
ответ дан 3 November 2019 в 00:05
поделиться

Проблема состоит в том, как только Ваша структура/класс не является экстерном "C", компиляторы C++ являются бесплатными перестроить и оптимизировать расположение Вашей структуры/класса, таким образом, Вы могли бы закончить с переупорядоченной структурой в зависимости от Вашего компилятора.

Существует препроцессор (например, пакет #pragma) флаги для C как поведение, но они не являются портативными в большинстве случаев.

0
ответ дан 3 November 2019 в 00:05
поделиться

Вы могли объявить типы POD в базовом классе, затем расширить тот класс (возможно, с private наследование) для добавления дополнительной функциональности.

Обновление Вашего обновления: Поскольку экземпляр derived_non_pod может также рассматриваться как a base_pod, поэтому смещения к элементам данных должны быть тем же. Относительно реализации Ваш компилятор выделит vtable указатель после полей base_pod при разметке derived_non_pod структура.

Мне приходит в голову, что при использовании частного наследования компилятор может принимать решение переупорядочить поля данных. Это вряд ли сделает так, однако, и создание защищенного наследования или общественность избежало бы этого возможного прерывания.

3
ответ дан 3 November 2019 в 00:05
поделиться

Был бы с помощью указателя на членскую работу вместо offsetof ()? Я знаю, что необходимо было бы, вероятно, сделать все виды кастинга, чтобы смочь на самом деле использовать указатель, так как я предполагаю, что InsertMember действует на тип, указанный в последнем параметре во времени выполнения.

Но с Вашим текущим решением Вы уже обходите систему типов, таким образом, я не уверен что Ваша потеря чего-либо там. За исключением того, что синтаксис для указателей на участника отвратителен.

0
ответ дан 3 November 2019 в 00:05
поделиться

Я почти уверен, что ответ Роула ] вместе с учетом ответа покрывает большую часть того, о чем вы спрашиваете.

struct A
{
  int i;
};

class B: public A
{
public:
  virtual void foo ()
  {
  }
};

int main ()
{
  std::cout << offsetof (B, A::i) << std::endl;
}

С g ++ вышеприведенный вывод 4, чего и следовало бы ожидать, если у B есть vtable перед членом базового класса 'i '.

Однако должно быть возможно вычислить смещение вручную, даже для случая, когда есть виртуальные базы:

struct A1 {
  int i;
};

struct A2 {
  int j;
};

struct A3 : public virtual A2 {
};

class B: public A1, public A3 {
public:
  virtual void foo () {
  }
};

template <typename MostDerived, typename C, typename M>
ptrdiff_t calcOffset (M C::* member)
{
  MostDerived d;
  return reinterpret_cast<char*> (&(d.*member)) - reinterpret_cast<char*> (&d);
}

int main ()
{
  B b;
  std::cout << calcOffset<B> (&A2::j) << ", " 
            << calcOffset<B> (&A1::i) << std::endl;
}

С g ++ эта программа выводит 4 и 8. Опять же, это согласуется с vtable в качестве первого члена из B, за которым следует виртуальная база A2 и ее член 'j'. Наконец, невиртуальная база A1 и ее член «i».

Ключевым моментом является то, что вы всегда вычисляете смещения на основе самого производного объекта, т.е. Б. Если участники являются частными, вам может потребоваться добавить вызов getMyOffset для каждого члена. Этот вызов выполнит вычисление там, где имя доступно.

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

struct H5MemberDef
{
  const char * member_name;
  ptrdiff_t offset;
  H5PredType h5_type;
};


class B  // ....
{
public:

  // ...

  static H5memberDef memberDef[];
};

H5MemberDef B::memberDef[] = {
  { "i", calcOffset<B> (&A1::i), H5::PredType::NATIVE_INT }
  , { "j", calcOffset<B> (&A2::j), H5::PredType::NATIVE_INT }
  , { 0, 0, H5::PredType::NATIVE_INT }
};

И затем вы можете построить H5type с помощью цикла:

H5::CompType func_that_creates_example_CompType(H5MemberDef * pDef) {
  H5::CompType ct;
  while (*pDef->member_name != 0)
  {
    ct.insertMember(pDef->member_name, pDef->offset, pDef->h5_type);
    ++pDef;
  }
  return ct;
}

Теперь, если вы добавите член в B или один из его основания, то простое добавление к этой таблице приведет к созданию правильного типа HDF.

1
ответ дан 3 November 2019 в 00:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: