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.