C++ C++;ODB数据库映射器:无法在关系中使用std::weak_ptr

C++ C++;ODB数据库映射器:无法在关系中使用std::weak_ptr,c++,c++11,odb,C++,C++11,Odb,我正在尝试与ODB建立一对多关系模型。我基本上是在尝试在 我必须对关系的一方使用std::weak_ptr,以避免循环所有权问题。然而,我的非常简单的示例代码并没有编译,因为ODB似乎不能很好地处理std::weak_ptr 在我的示例中,每个Bar都有一个Foo,而每个Foo都有多个Bars。这是我的代码: #include <odb/core.hxx> #include <string> #include <memory> #include <vec

我正在尝试与ODB建立一对多关系模型。我基本上是在尝试在

我必须对关系的一方使用
std::weak_ptr
,以避免循环所有权问题。然而,我的非常简单的示例代码并没有编译,因为ODB似乎不能很好地处理std::weak_ptr

在我的示例中,每个
Bar
都有一个
Foo
,而每个
Foo
都有多个
Bar
s。这是我的代码:

#include <odb/core.hxx>
#include <string>
#include <memory>
#include <vector>

// Forward
class Foo;

#pragma db object
class Bar {
public:
    // A Bar has exactly *one* Foo
    #pragma db not_null
    std::shared_ptr<Foo> cfg;

private:
    #pragma db id auto
    unsigned long id_;
    friend class odb::access;
};

#pragma db object
class Foo {
public:
    // A Foo has multiple Bars
    // Using std::weak_ptr here instead of std::shared_ptr to avoid circular
    // ownership
    #pragma db value_not_null inverse(cfg)
    std::vector<std::weak_ptr<Bar>> entries;

private:
    #pragma db id auto
    unsigned long id_;
    friend class odb::access;
};

int main() {}
#包括
#包括
#包括
#包括
//前进
Foo类;
#pragma数据库对象
分类栏{
公众:
//一个酒吧正好有一个Foo
#pragma db not_null
std::共享\u ptr cfg;
私人:
#pragma db id自动
无符号长id;
朋友类odb::access;
};
#pragma数据库对象
福班{
公众:
//一个Foo有多个条
//在此处使用std::weak_ptr而不是std::shared_ptr以避免循环
//所有权
#pragma db值\u非\u空逆(cfg)
std::向量条目;
私人:
#pragma db id自动
无符号长id;
朋友类odb::access;
};
int main(){}
我使用以下命令生成数据库代码:

odb—std c++11—数据库sqlite—生成查询—生成模式 --立刻main.hpp

我这样编译:

g++--std=c++11 main.hpp main-odb.cxx

(我知道链接时会崩溃——我只是想让它编译。)

我的编译器(GCC 7)告诉我:

main-odb.cxx: In static member function ‘static void odb::access::object_traits_impl<Foo, (odb::database_id)1u>::entries_traits::init(odb::access::object_traits_impl<Foo, (odb::database_id)1u>::entries_traits::value_type&, const odb::access::object_traits_impl<Foo, (odb::database_id)1u>::entries_traits::data_image_type&, odb::database*)’:
main-odb.cxx:794:43: error: no matching function for call to ‘std::weak_ptr<Bar>::weak_ptr(odb::object_traits<Bar>::pointer_type)’
             obj_traits::object_type > (id));
                                           ^
In file included from /usr/include/c++/5/memory:82:0,
                 from main.hpp:3,
                 from main-odb.hxx:16,
                 from main-odb.cxx:7:
/usr/include/c++/5/bits/shared_ptr.h:492:2: note: candidate: template<class _Tp1, class> std::weak_ptr<_Tp>::weak_ptr(std::weak_ptr<_Tp1>&&)
  weak_ptr(weak_ptr<_Tp1>&& __r) noexcept
  ^
/usr/include/c++/5/bits/shared_ptr.h:492:2: note:   template argument deduction/substitution failed:
main-odb.cxx:794:43: note:   mismatched types ‘std::weak_ptr<_Tp>’ and ‘odb::object_traits<Bar>::pointer_type {aka Bar*}’
             obj_traits::object_type > (id));
main-odb.cxx:在静态成员函数“static void odb::access::object\u traits\u impl::entries\u traits::init(odb::access::object\u traits\u impl::entries\u traits::value\u type&,const odb::access::object\u traits\u impl::entries\u traits::data\u image\u type&,odb::database*):
main odb.cxx:794:43:错误:调用“std::weak_ptr::weak_ptr(odb::object_traits::pointer_type)”时没有匹配的函数
对象特性::对象类型>(id));
^
在/usr/include/c++/5/memory:82:0中包含的文件中,
从主水电站:3,
从主odb.hxx:16,
从主odb.cxx:7:
/usr/include/c++/5/bits/shared_ptr.h:492:2:注:候选:模板std::弱_ptr::弱_ptr(std::弱_ptr&)
弱ptr(弱ptr&&&uur)无例外
^
/usr/include/c++/5/bits/shared_ptr.h:492:2:注意:模板参数推导/替换失败:
main odb.cxx:794:43:注意:不匹配的类型“std::weak_ptr”和“odb::object_traits::pointer_type{aka Bar*}”
对象特性::对象类型>(id));
还有三个候选人我跳过了。重要的部分:ODB试图在某处从
条*
创建
std::weak_ptr
,这显然是不可能的。它必须从
std::shared\u ptr
创建它。然而,ODB文档明确指出在这些情况下应该(事实上必须)使用
std::weak_ptr


我做错了什么?

好的,我想出了一个解决方案(不确定这是否是最好的解决方案):

您可以强制ODB在任何地方使用
std::shared_ptr
而不是
Bar*
。通过将类定义为:

#pragma db object pointer(std::shared_ptr)
class Bar {
...

这样,当创建一个
std::weak_ptr
时,它是从一个
std::shared_ptr
创建的,它可以工作。您还可以指定要在命名空间或全局范围中使用的指针类型,请参见

Bar包含指向Foo的指针,尝试在Foo中使用std::enable\u shared\u。这是一个好主意-但是,ODB中的代码尝试从
Bar*
创建
std::weak\u ptr
。我不知道如何使用
Bar::shared\u from\u this()
?实现从
Bar
std::shared_ptr
(这将是
std::weak_ptr
构造函数的有效参数)的用户定义转换也不起作用,因为它使用的是
Bar*
,而不是
Bar