3

I'm writing a small C++ module for Python. In this module I set connection to different databases. Connection to one of those databases is set like so:

std::unique_ptr<R::Connection> conn = R::connect("localhost", 28015);

After I set connection, I want to return this connection variable. The way I do it is using vector and variant (since I may return multiple things in a vector - database connection, some extra parameters etc).

This is how I define variant and vector types:

typedef variant<std::unique_ptr<R::Connection>,....connections to other databases> VariantData;
typedef std::vector<VariantData> vector;

And, finally, this is how I return a vector right after I set connection:

return vector{conn, ""};

As a result, I get a long list of errors. However, this trick works well with other clients which set connections to other databases and do not use unique_ptr. So, I think I need something like casting std::unique_ptr<R::Connection> to Connection * or something like that, to be able to use conn variable like a general pointer.

EDIT

With these snippets of code:

typedef variant<R::Connection * ,....connections to other databases> VariantData;
typedef std::vector<VariantData> vector;

... function body
... code which does not matter
std::unique_ptr<R::Connection> conn = R::connect("localhost", 28015);
return vector{move(conn),""};

And this is the error messages I get:

n file included from /usr/include/boost/variant.hpp:17:0,
             from corm.cpp:4:
/usr/include/boost/variant/variant.hpp: In instantiation of ‘typename   boost::enable_if<boost::is_rvalue_reference<T&&> >::type boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::convert_construct(T&&, int, mpl_::false_) [with T = std::unique_ptr<RethinkDB::Connection>; T0_ = mysqlpp::Connection*; T1 = mongo::DBClientBase*; T2 = pqxx::basic_connection<pqxx::connect_direct>*; T3 = sqlite3**; T4 = IBPP::Ptr<IBPP::IDatabase>; T5 = RethinkDB::Connection*; T6 = const char*; T7 = boost::detail::variant::void_; T8 = boost::detail::variant::void_; T9 = boost::detail::variant::void_; T10 = boost::detail::variant::void_; T11 = boost::detail::variant::void_; T12 = boost::detail::variant::void_; T13 = boost::detail::variant::void_; T14 = boost::detail::variant::void_; T15 = boost::detail::variant::void_; T16 = boost::detail::variant::void_; T17 = boost::detail::variant::void_; T18 = boost::detail::variant::void_; T19 = boost::detail::variant::void_; typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type = void; mpl_::false_ = mpl_::bool_<false>]’:
/usr/include/boost/variant/variant.hpp:1789:62:   required from ‘boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::variant(T&&, typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type*, typename boost::disable_if<boost::is_const<FunctionObj> >::type*) [with T = std::unique_ptr<RethinkDB::Connection>; T0_ = mysqlpp::Connection*; T1 = mongo::DBClientBase*; T2 = pqxx::basic_connection<pqxx::connect_direct>*; T3 = sqlite3**; T4 = IBPP::Ptr<IBPP::IDatabase>; T5 = RethinkDB::Connection*; T6 = const char*; T7 = boost::detail::variant::void_; T8 = boost::detail::variant::void_; T9 = boost::detail::variant::void_; T10 = boost::detail::variant::void_; T11 = boost::detail::variant::void_; T12 = boost::detail::variant::void_; T13 = boost::detail::variant::void_; T14 = boost::detail::variant::void_; T15 = boost::detail::variant::void_; T16 = boost::detail::variant::void_; T17 = boost::detail::variant::void_; T18 = boost::detail::variant::void_; T19 = boost::detail::variant::void_; typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type = void; typename boost::disable_if<boost::is_const<FunctionObj> >::type = void]’
corm.cpp:94:39:   required from here
/usr/include/boost/variant/variant.hpp:1615:17: error: no matching function for call to ‘boost::variant<mysqlpp::Connection*, mongo::DBClientBase*, pqxx::basic_connection<pqxx::connect_direct>*, sqlite3**, IBPP::Ptr<IBPP::IDatabase>, RethinkDB::Connection*, const char*>::initializer::initialize(void*, boost::remove_reference<std::unique_ptr<RethinkDB::Connection>&>::type)’
             )
             ^
/usr/include/boost/variant/variant.hpp:1615:17: note: candidates are:
In file included from /usr/include/boost/variant/variant.hpp:33:0,
             from /usr/include/boost/variant.hpp:17,
             from corm.cpp:4:
/usr/include/boost/variant/detail/initializer.hpp:104:24: note: static int boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::initialize(void*, boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::param_T) [with BaseIndexPair = boost::mpl::pair<boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::initializer_root, mpl_::int_<0> >, 
>::initializer_node::param_T {aka RethinkDB::Connection* const&}’
Makefile:45: recipe for target 'corm.o' failed
make: *** [corm.o] Error 1

EDIT

This is the code (minimized)

#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/variant.hpp>
#include <vector>
#include <memory>
#include <rethinkdb.h>

using namespace boost;
using namespace boost::python;
namespace Ret = RethinkDB;

typedef variant<Ret::Connection *, const char*> VariantData;
typedef std::vector<VariantData> vector;

class ORM{
private:
    int idx;
public:
    ORM(int _idx){
      this->idx = _idx;
    }
    vector Connect(){
        if(this->idx == 8){
            std::unique_ptr<Ret::Connection> conn = Ret::connect(this->host, this->port);
            return vector{std::move(conn), ""};
        }
    }
};


struct variant_to_object:static_visitor<PyObject*>{
   static result_type convert(VariantData const& v){
      return apply_visitor(variant_to_object(), v);
   }
   template<typename T>
   result_type operator () (T const& v) const{
      return incref(object(v).ptr());
   }
};

BOOST_PYTHON_MODULE(corm){   

   class_<vector>("vector").def(vector_indexing_suite<vector, true>());
   to_python_converter<VariantData, variant_to_object>();
   implicitly_convertible<Ret::Connection *, VariantData>();
   implicitly_convertible<const char*, VariantData>();   

   class_<ORM>("ORM",
     init<int>())
     .def("Connect", &ORM::Connect);

}

Client for rethinkdb is taken from here.

Jacobian
  • 10,122
  • 29
  • 128
  • 221
  • 3
    Maybe `return vector{std::move(conn), ""};` – Aaron McDaid Jul 29 '15 at 13:10
  • 1
    @AaronMcDaid, that should be `std::move`, never call `move` unqualified. – Jonathan Wakely Jul 29 '15 at 13:11
  • 1
    @JonathanWakely, edited. In fact, I'm confused by the use of (non-`std`) `vector` here too :-) – Aaron McDaid Jul 29 '15 at 13:12
  • 2
    We are interested in the long list of errors. – Quentin Jul 29 '15 at 13:12
  • I've already tried this and it does not work. By the way, in this case, how should I typedef my VariantData? Like `typedef variant...` or like typedef variant – Jacobian Jul 29 '15 at 13:12
  • I will post the list of errors in a minute. – Jacobian Jul 29 '15 at 13:13
  • Also, what is this `variant` type? Where did you find it? Is it in Boost? Also, is this function returning to Python? If not, then maybe Python has no real relevance to this question? – Aaron McDaid Jul 29 '15 at 13:15
  • Yes, it is in boost. – Jacobian Jul 29 '15 at 13:15
  • 1
    Variant can only be used with copy-constructible types. See [this question](http://stackoverflow.com/questions/15689793/boostvariant-stdunique-ptr-and-copy). – vukung Jul 29 '15 at 13:17
  • I think `using std::vector` is clearer than `typedef` to indicate bringing in namespaced entities. Plus, syntactically, it's nicer in any case. (However, I always explicitly specify things from `std` and the like, and I'd say this whole snippet is an argument for that. :P) – underscore_d Jul 29 '15 at 13:18
  • Can you provide a stand alone compilable (or not) example that demonstrates the issue without the irrelevant parts? – Galik Jul 29 '15 at 13:24
  • Yes, I can. But it may take some time for me to prepare. I guess about 5-10 minutes – Jacobian Jul 29 '15 at 13:26
  • 3
    You should have spent those 5-10 minutes to do it before wasting other people's time. – Jonathan Wakely Jul 29 '15 at 13:29
  • I'm going to edit the title. "vector of unique_ptr" is wrong. I'll go for "std::vector of boost::variant of std::unique_ptr". A bit pedantic perhaps, but this question does weird things with `vector` – Aaron McDaid Jul 29 '15 at 13:31
  • Your variant type is declared as having a `Ret::Connection *` but you are trying to put a `std::uniqur_ptr` into your vector. Maybe declare the variant type as taking a `std::unique_ptr`? – Galik Jul 29 '15 at 15:25

0 Answers0