2012-10-02 59 views
1

我试图在的Mac OS X中构建一个大项目,并遇到以下我无法解决的错误。构建错误:基本说明符必须命名一个类

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"); 
    } 
} 

难道是用编译器IM有问题吗?

+0

是派生类模板吗? – juanchopanza

+0

@juanchopanza,我无意中插入了错误的代码片段。这是纠正! – JavaCake

+1

它看起来像你的模板参数'T'解析为一个整型。你怎么调用静态函数'save'? – juanchopanza

回答

2

我觉得我可能会负责提到的代码段。虽然有些东西缺失,并且多个人已经注意到了这一点。目前看起来是这样的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; 

软件的序列部分进行尚未使用,但它在构建系统结束了反正。如果你注释掉src/rwlibs中CMakeLists.txt的serialize目录,那么它应该可以工作。或添加写入功能一个unsigned long:

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

是的,我没有考虑Boost.Serialization进军创建另一个序列化框架之前。然而,我试图创造一些不那么具有侵入性,模板化程度更低,用户更友好的东西....猜猜我失败了......

+0

我收到了Dirk的更正,我稍后再尝试。非常感谢! – JavaCake

3

这两个错误都指向相同:您试图将您的模板与非课程,最可能是unsigned int。在第一种情况下,您将试图从unsigned int继承Derived,这是非法的;在第二种情况下,您将尝试在unsigned int上调用静态方法(save()),这种方法又是非法的。查看调用模板的代码可以澄清问题。

更新:从添加到问题的信息我们现在可以得出结论,确实如此。 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(),这取决于你有什么可用。

+0

代码调用现在包含在内。 – JavaCake

+0

现在我们需要调用'write()'的代码。我们仍然不知道那里有什么'T'。 – Gorpik

+0

@JavaCake:你只包括立即调用代码,它仍然是模板。该错误源自堆栈的更上方。你用'unsigned int'引用调用'write'作为第一个参数。然而,这种用法很可能会起作用,所以我们应该关注如何修复模板以处理非类类型。 –

1

首先,最好使用像Boost.Serialization这样的现有解决方案。它已经被调试并且适用于您可能需要的所有情况。

但是,您仍然应该知道您当前的代码在哪里存在问题以及如何执行此类模板设计。所以:

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

这是unsigned int。你确实需要序列化它。所以你需要一个写,可以接受原始类型。有两个选项:

基本类型
  1. 写非模板重载。非模板重载优先于模板重载,所以如果使用unsigned int第一个参数编写明确的非模板重载,模板将不会被实例化,并且不会有任何错误。但是,您将分别为每种可能的基元类型分别重载,因为完全匹配的模板将优于需要转换的非模板重载。

  2. 使用免费保存功能而不是方法。方法的优点是它可以是虚拟的,但通常不需要模板。自由函数的优点是可以为非类类型定义它们,并且可以为已经存在的类定义它们,这两者在模板中通常都需要。因此,您可以将所有save方法的实例更改为自由函数,将has_save_func全部删除,并为需要的基元类型重载save函数。

  3. 修改has_save_func并检查模板参数是否为类类型。非班级类型没有方法,所以这就是其他变体所要做的。您可以使用boost::is_class或实施类似的东西。 Boost实际上通过枚举所有其他选项来实现它,但它也可以使用指向成员的指针来实现,当给定非类类型时它会引起SFINAE。不幸的是,当给定类的类型时,你没有任何东西可以导致SFINAE,所以你必须将它和函数模板和sizeof结合起来,最终得到非常棘手的东西(我确信我已经看到它,但是实际上不记得它)。

相关问题