How to use mongocxx with inline namespaces and PIMPL idiom?

Viewed 129

I want to write an interface to mongocxx using the PIMPL idiom. The interface itself works but I did something wrong with mongocxx inline namespaces because writing tests is not working.

This is a minimal example:

MongoInterface.h:

#pragma once
#include <memory>

namespace mongocxx
{
    namespace v_noabi
    {
        class instance;
    }
}

class MongoInterface
{
public:
    MongoInterface();
    virtual ~MongoInterface();

protected:
    std::unique_ptr<mongocxx::v_noabi::instance> mp_instance;
};

MongoInterface.cpp:

#include <mongocxx/instance.hpp>
#include <libsystem/MongoInterface.h>

MongoInterface::MongoInterface()
: mp_instance(nullptr)
{
    mp_instance = std::make_unique<mongocxx::instance>();
}

MongoInterface::~MongoInterface() = default;

The test I simulate with a main.cpp:

#include <mongocxx/instance.hpp>
//#include <libsystem/MongoInterface.h>

int main(int /*argc*/, char* /*argv*/[])
{
    mongocxx::instance instance{};
}

The code exactly as above compiles. But when I include line 2 of main.cpp it fails saying

In file included from /home/user/Development/3rdparty/mongo-cxx-driver/3.5.0/build/install/include/mongocxx/v_noabi/mongocxx/config/prelude.hpp:58,
                 from /home/user/Development/3rdparty/mongo-cxx-driver/3.5.0/build/install/include/mongocxx/v_noabi/mongocxx/instance.hpp:19,
                 from /home/user/Development/sim-cad/source/examples/mongodb/playground/main_mongoPlayground.cpp:2:
/home/user/Development/3rdparty/mongo-cxx-driver/3.5.0/build/install/include/mongocxx/v_noabi/mongocxx/config/config.hpp:15:58: error: inline namespace must be specified at initial definition
   15 | #define MONGOCXX_INLINE_NAMESPACE_BEGIN inline namespace v_noabi {
      |                                                          ^~~~~~~
/home/user/Development/3rdparty/mongo-cxx-driver/3.5.0/build/install/include/mongocxx/v_noabi/mongocxx/instance.hpp:22:1: note: in expansion of macro ‘MONGOCXX_INLINE_NAMESPACE_BEGIN’
   22 | MONGOCXX_INLINE_NAMESPACE_BEGIN
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I guess I made something wrong with the implementation of MongoInterface. I do not really understand the inline namespaces of mongocxx and found my implementation by trial and error. Does someone has a hint how to better implement the interface classes?

1 Answers

You should not be naming the v_noabi namespace at all. That namespace is inline, as it exists to allow a future version of mongocxx to have a different ABI. This means that it is not possible to reliably forward declare things like mongocxx::instance. This is actually a very interesting observation (to me, as the original mongocxx designer) and I would consider it a defect. Please see https://blog.libtorrent.org/2017/12/forward-declarations-and-abi/ for some additional details. I would suggest that you open a ticket in the mongocxx JIRA project, and reference this discussion. The answer is probably to produce bsoncxx_fwd.hpp and mongoocxx_fwd.hpp files which contain proper forward declarations for all types in the respective libraries.

Related