【问题标题】:serialize is not a member of std::unique_ptr序列化不是 std::unique_ptr 的成员
【发布时间】:2013-03-13 20:33:39
【问题描述】:

这个问题更适合 Boost 论坛吗?下面引用了完整的代码,与本网站上的其他 unique_ptr 示例相比,我不认为我错误地尝试将 auto_ptr 序列化示例转换为 unique_ptr 示例。因此,为什么我会在 Boost 库的深处收到编译错误?我之前在标准容器上使用过 Boost 序列化没有问题,虽然这是一个自定义适配器,但如果编译了类似的示例,为什么不这样做呢?

我引用了http://www.boost.org/doc/libs/1_51_0/libs/serialization/example/demo_auto_ptr.cpp 以尝试使用自定义适配器序列化我的二叉树。下面是代表 sscce 的代码转储。

// disables conversion from 'std::streamsize' to 'size_t', possible loss of data
#pragma warning(disable:4244)  

#ifndef BINARY_SEARCH_TREE_H_
#define BINARY_SEARCH_TREE_H_

#include<functional>

#include<memory>
#include<fstream>
#include<boost/archive/binary_oarchive.hpp>
#include<boost/archive/binary_iarchive.hpp>

#define BST_FILE_NAME "tree.dat"    // default filename used to save and load

namespace boost { 

    namespace serialization {

        template <class Archive, class T>
        inline void save
            (Archive &archive, 
            const std::unique_ptr<T> &subtree,  
            const unsigned int file_version)
        {
            // only the raw pointer has to be saved
            const T *const  subtree_x = subtree.get();

            archive << subtree_x;
        }

        template <class Archive, class T>
        inline void load
            (Archive &archive, 
            const std::unique_ptr<T> &subtree, 
            const unsigned int file_version)
        {

            T *p_subtree;

            archive >> p_subtree;

            #if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
                subtree.release();
                subtree = std::unique_ptr< T >(p_subtree);
            #else
                subtree.reset(p_subtree);
            #endif
        }

        template <class Archive, class T>
        inline void serialize
            (Archive &archive, 
            const std::unique_ptr<T> &subtree, 
            const unsigned int file_version)
        {
            boost::serialization::split_free(archive, subtree, file_version);
        }

    } // namespace serialization
} // namespace boost


template <class T = int>
class BinarySearchTree{

    class BinarySearchTreeNode{
    public:

        std::unique_ptr<BinarySearchTreeNode> node_factory(const T &new_key, const T    &new_index){
            return std::unique_ptr<BinarySearchTreeNode>(new    BinarySearchTreeNode(new_key, new_index)); }

        BinarySearchTreeNode(BinarySearchTreeNode &&other) : key(other.key), index(other.index), left(std::move(other.left)), 
            right(std::move(other.right)) {key = index = left = right = nullptr; }

        BinarySearchTreeNode &operator=(BinarySearchTreeNode &&rhs) { if(this != rhs) { key = rhs.key; index = rhs.index; 
            left = std::move(rhs.left); right = std::move(rhs.right); 
            rhs.key = rhs.index = rhs.left = rhs.right = nullptr;} return *this;}

        ~BinarySearchTreeNode() {}  // Note to self; don't hide the destructor

        friend class BinarySearchTree;

    private:

        friend class boost::serialization::access;
        template<class Archive>
        void serialize(Archive &archive, const unsigned int /* file_version */){
            archive & key;
            archive & index;
            archive & left;
            archive & right;
        }

        T key;
        long index;

        std::unique_ptr<BinarySearchTreeNode> left;
        std::unique_ptr<BinarySearchTreeNode> right;

        BinarySearchTreeNode() {}
        BinarySearchTreeNode(const T &new_key, const T &new_index) :key(new_key), index(new_index), 
                                    left(nullptr), right(nullptr) {}

    };

    std::unique_ptr<BinarySearchTreeNode> root;

    std::list<T> tree_keys;
    std::list<long> tree_indicies;



    friend class boost::serialization::access;
    template <class Archive>
    void serialize(Archive &archive, const unsigned int version){
        archive & root;
    }



    BinarySearchTree(const BinarySearchTree &other){}
    BinarySearchTree &operator=(const BinarySearchTree &rhs){}

    std::unique_ptr<BinarySearchTreeNode> insert(const T &new_key, const T &new_index, 
                std::unique_ptr<BinarySearchTreeNode> &tree){
        if(tree == nullptr){
            return root->node_factory(new_key, new_index);
        }else if(std::less<T> () (new_key, tree->key)){ // Left insertion
            tree->left = insert(new_key, new_index, tree->left);
            return std::move(tree);
        }else {   // Right insertion
            tree->right = insert(new_key, new_index, tree->right);
            return std::move(tree);
        }
    }

public:
    BinarySearchTree() : root(nullptr) {}
    BinarySearchTree(BinarySearchTree &&other) : root(std::move(other.root)) { other.root = nullptr; }
    BinarySearchTree &operator=(BinarySearchTree &&rhs) { if(this != rhs) { root = std::move(rhs.root); 
        rhs.root = nullptr} return *this; }
    bool insert_into_tree(const T &new_key, const T &new_index){
        if(new_key == NULL){
            return false;
        }
        root = std::move(insert(new_key, new_index, root));
        return true;
    }


    void save(const BinarySearchTree &tree)
    {
        // create and open a binary archive for output
        std::ofstream writer(BST_FILE_NAME, std::ofstream::out | std::ofstream::binary);

        if(writer){
            boost::archive::binary_oarchive serial_writer(writer);
            //set_flags(0, true);
            // write class instance to archive
            serial_writer << tree;
            // archive and stream closed when destructors are called

        }else if(writer.fail()){
            writer.clear();
        }
    }

    void load(BinarySearchTree &tree)
    {
        // create and open a binary archive for output
        std::ifstream reader(BST_FILE_NAME, std::ifstream::in | std::ifstream::binary);

        if(reader){
            boost::archive::binary_iarchive serial_reader(reader);
            // read class state from archive
            serial_reader >> tree;
            // archive and stream closed when destructors are called

        }else if(reader.fail()){
            reader.clear();
        }
    }
    ~BinarySearchTree() {}
};

#endif

上面的代码与树成员函数的任何用法一样编译。一旦选择调用保存,即出现编译器错误。这是主要的:

#include<cstdlib>

#include "physical_view.h"

using namespace std;

int main(int argc, char *argv[]){


    BinarySearchTree<> tree;

    tree.insert_into_tree(10, 5);
    tree.insert_into_tree(5, 15);
    tree.insert_into_tree(15, 10); <--------- All is wonderful to here!

    tree.save(tree); <---------- Compiler unhappy here!

    return EXIT_SUCCESS;
}

那个编译器错误怎么样:

Error   1   error C2039: 'serialize' : is not a member of 'std::unique_ptr<_Ty>'    c:\boost_12\include\boost-1_53_1\boost\serialization\access.hpp 118

感谢您帮助我解决此编译器错误。

【问题讨论】:

  • 你能显示准确真实代码吗,看来你有一堆语法错误。
  • 尤其是您添加到“boost::serialization”的附加功能,尤其是序列化功能,因为我怀疑这就是您的错误所在。
  • 代码对于转储来说太长了,但我可以说代码编译 100% 直到我准备好执行 boost::archive::text_oarchive(some stream) 然后我得到错误。如果您仍想查看所有代码,请告诉我。
  • @user633658:void serialize(Archive &amp;archive, const unsigned int version){archive &amp; root;} 这行没有多大意义,因为Archive 是一个模板参数。另外,您缺少大括号等。请尝试提供sscce
  • 已注明,有机会我会提供 sscce。

标签: c++ boost c++11 unique-ptr boost-serialization


【解决方案1】:

您的序列化和加载函数的签名不正确。 std::unique_ptr&lt;T&gt; 参数对于它们都必须是非常量的。由于它无法推断类型(由于 const),它只是忽略了重载,根本找不到它。

【讨论】:

  • 解释得很好,解释得很好。问题解决了。我确实注意到我(错误地)将 const 留在了加载函数的第二个参数上,只要我从序列化中删除了 const,它仍然可以编译,但我已经删除了两者。
猜你喜欢
  • 2013-08-07
  • 2013-07-26
  • 1970-01-01
  • 1970-01-01
  • 2012-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多