[odb-users] Using std::weak_ptr

Lukas Barth lists at tinloaf.de
Thu Aug 2 07:59:15 EDT 2018


[ This question was cross-posted to StackOverflow. If you want to see
the code in a better formatted way and / or grab SO reputation for your
answer, head to
https://stackoverflow.com/questions/51652818/c-odb-database-mapper-unable-to-use-stdweak-ptr-in-relationship
]

Hi,

I'm trying to model a one-to-many relationship with ODB. I'm basically
trying to recreate the example in
https://www.codesynthesis.com/products/odb/doc/manual.xhtml#6.2.2

I have to use std::weak_ptr for one side of the relationship, to avoid
circular ownership issues. However, my very simple example code does not
compile, as ODB doesn't seem to play nicely with std::weak_ptr.

In my example, every Bar has exactly one Foo, while every Foo has
multiple Bars. This is my code:

================ [Begin of main.hpp] ==================

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

// Forward
class Foo;

#pragma db object
class Bar {
public:
    // A DBConfigKV has exactly *one* DBConfig
    #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() {}

================ [End of main.hpp] ==================

I generate the database code with

> odb --std c++11 --database sqlite --generate-query --generate-schema \
> --at-once main.hpp

and compile with

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

(I know that would crash at linking - I'm just trying to get it to compile.)

My compiler (GCC 7) tells me:

================ [Begin compiler output] ==================
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));
================ [End compiler output] ==================

There are three more candidates which I skipped. The important part: ODB
tries somewhere to create a std::weak_ptr<Bar> from a Bar *, which is
obviously not possible. It would have to create it from a
std::shared_ptr<Bar>. However, the ODB documentation explicitly says one
should (and in fact must) use std::weak_ptr in these cases.

What am I doing wrong?

Thanks a lot,

Lukas



More information about the odb-users mailing list