Ошибка сборки: базовый спецификатор должен называть класс

Я пытаюсь построить большой проект в Mac OS X с cmake и столкнулся со следующей ошибкой, которую я не могу решить.

Archive.hpp:92:30: error: base specifier must name a class
struct Derived : T, Fallback { };

Код:

template<typename T>
class has_save_func
{
struct Fallback { int save; }; // add member name "X"struct Derived : T, Fallback { };
...

Кроме того, у меня есть следующее:

Archive.hpp:137:13: error: type 'unsigned long' cannot be used prior to '::'

Код:

template <class A>
static bool save(const A& data, class OutputArchive& oarchive, const std::string& id, typename boost::enable_if_c<has_save_func<A>::value, A>::type* def=NULL){
// todo check if A actually is friend with Access class, else return false
A::save(data, oarchive); // ! Error on this line !
return true;
}

template <class A>
static bool save(const A& data, class OutputArchive& oarchive, const std::string& id, typename boost::disable_if_c<has_save_func<A>::value, A>::type* def=NULL){
// todo check if A actually is friend with Access class, else return false
return serialization::save<A>( data, oarchive, id);
}

Вызов кода (OutputArchive.hpp):

template<class T>
void write(const T& data, const std::string& id){
// the data method must have an implementation of load/save and if not then we try the generic write
// method which could provide a solution by the implementation itself
writeEnterScope(id);
try {
Archive::Access::save<T>(data, *this, id);
} catch (...){
// we fall back to this call
boost::any adata(data);
write(adata, id);
}
writeLeaveScope(id);
}

Код serializeutil.cpp

void save(const rw::math::Q& tmp, OutputArchive& oar, const std::string& id){
oar.write(tmp.size(), "size");
for(int i=0;i<tmp.size();i++){
oar.write(tmp[i],"q");
}
}

Может ли быть проблема с компилятором, который я использую?

1

Решение

Я думаю, что я могу быть ответственным за упомянутые фрагменты кода. Что-то не хватает, хотя, и несколько человек уже заметили это. Перегруженные функции записи в OutputArchive, который в настоящее время выглядит примерно так:

virtual void writeEnterScope(const std::string& id) = 0;
virtual void writeLeaveScope(const std::string& id) = 0;
virtual void writeEnterArray(const std::string& id) = 0;
virtual void writeLeaveArray(const std::string& id) = 0;

// writing primitives to archive
virtual void write(bool val, const std::string& id) = 0;

virtual void write(int val, const std::string& id) = 0;
virtual void write(unsigned int val, const std::string& id){ write((int)val,id); }

virtual void write(boost::uint64_t val, const std::string& id) = 0;
virtual void write(double val, const std::string& id) = 0;
virtual void write(const std::string&  val, const std::string& id) = 0;

Сериализационная часть программного обеспечения еще не должна была использоваться, но она все равно оказалась в системе сборки. Если вы закомментируете каталог serialize в CMakeLists.txt в src / rwlibs, тогда он должен работать. Или добавьте функцию записи для unsigned long:

virtual void write(unsigned long val, const std::string& id){};

И да, я изучил Boost.Serialization, прежде чем решиться создать еще одну инфраструктуру сериализации. Однако я пытался создать что-то, что было бы менее навязчивым, менее шаблонным и более удобным для пользователя …. Думаю, я потерпел неудачу в этом …

2

Другие решения

Обе ошибки указывают на одно и то же: вы пытаетесь использовать ваши шаблоны с неклассом, скорее всего unsigned int, В первом случае вы бы пытались иметь Derived наследовать от unsigned int, что является незаконным; во втором вы пытаетесь вызвать статический метод (save()) на unsigned int, что опять незаконно. Просмотр кода, вызывающего шаблоны, прояснит проблему.

ОБНОВЛЕНИЕ: Из информации, добавленной к вопросу, мы теперь можем сделать вывод, что это действительно так. tmp.size(), скорее всего, unsigned intтак ты звонишь oar.write() с unsigned int; это, в свою очередь, звонки save() с unsigned intтак он пытается позвонить unsigned int::save(), который является незаконным, и экземпляр класса has_save_func<unsigned int>, который пытается определить struct Derived : unsigned int, Fallback что опять незаконно.

Боюсь, вам нужно будет изменить дизайн ваших классов, если вы хотите, чтобы они работали со встроенными типами, такими как unsigned int, Вы можете сделать полный редизайн или просто перегрузить функции write() или же save()в зависимости от того, что у вас есть в наличии.

3

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

Тем не менее, вы все равно должны знать, где у вашего текущего кода есть проблемы и как сделать механизм шаблонов подобным образом. Так:

oar.write(tmp.size(), "size");
^^^^^^^^^^

Это unsigned int, И вам нужно его сериализовать. Поэтому вам нужна запись, которая может принимать примитивные типы. Есть два варианта:

  1. Напишите не шаблонные перегрузки для примитивных типов. Не шаблонные перегрузки имеют приоритет над шаблонными, так что если вы пишете явную не шаблонную перегрузку с unsigned int Первый аргумент: шаблон не будет создан и не будет ошибок. Однако вам потребуются перегрузки для каждого возможного типа примитива отдельно, потому что шаблон, который точно соответствует шаблону, все равно будет предпочтительнее, чем шаблонная перегрузка, которая требует преобразования.

  2. Используйте бесплатную функцию сохранения вместо метода. Преимущество метода в том, что он может быть виртуальным, но вам обычно не нужно это с шаблоном. Преимущества свободной функции заключаются в том, что они могут быть определены для типов, не относящихся к классам, и что они могут быть определены для уже существующих классов, которые часто требуются в шаблонах. Таким образом, вы бы изменили все экземпляры save метод, чтобы освободить функцию, бросьте has_save_func в целом и перегрузить save функция для примитивных типов, которые вам нужны.

  3. Изменить has_save_func с проверкой, является ли аргумент шаблона типом класса. Неклассовые типы не имеют методов, так что это будет делать другой вариант. Вы можете использовать повышение :: is_class или реализовать нечто подобное. Boost фактически реализует его, перечисляя все остальные параметры, но он также может быть реализован с использованием указателя на член, который вызовет SFINAE, если задан тип, отличный от класса. К сожалению, у вас нет ничего, чтобы вызывать SFINAE при заданном типе класса, поэтому вы должны объединиться с шаблонами функций и sizeof и в итоге получить действительно хитрые вещи (я уверен, что я видел это, но на самом деле не помню этого ).

1
По вопросам рекламы [email protected]