boost::python string-convertible properties - c++

I have a C++ class, which has the following methods:
class Bar {
...
const Foo& getFoo() const;
void setFoo(const Foo&);
};
where class Foo is convertible to std::string (it has an implicit constructor from std::string and an std::string cast operator).
I define a Boost.Python wrapper class, which, among other things, defines a property based on previous two functions:
class_<Bar>("Bar")
...
.add_property(
"foo",
make_function(
&Bar::getFoo,
return_value_policy<return_by_value>()),
&Bar::setFoo)
...
I also mark the class as convertible to/from std::string.
implicitly_convertible<std::string, Foo>();
implicitly_convertible<Foo, std::string>();
But at runtime I still get a conversion error trying to access this property:
TypeError: No to_python (by-value) converter found for C++ type: Foo
How to achieve the conversion without too much boilerplate of wrapper functions? (I already have all the conversion functions in class Foo, so duplication is undesirable.

I ended up giving up and implementing something similar to custom string class conversion example in Boost.Python FAQ, which is a bit verbose, but works as advertised.

Related

Add implicit conversion from unique_ptr<T> to T*

General Question: Without going into whether or not it's a good idea, how can I add an implicit conversion operator to a class that has already been defined? For example, let's say that I want unique_ptr<T> to implicitly convert to T*, but I can't just add a member conversion operator because I can't change the definition of the unique_ptr class.
Options:
Is there some c++ voodoo that I can use to make this happen without creating a member function?Answer-So-Far: NO.There is no way to add an implicit conversion away from a type that you can't modify in code.Just ... sadness.
Could I derive from std::unique_ptr and add my own member conversion function? Are there any serious downsides to this?Answer-So-Far: Yes (from vsoftco)Downsides are yet to be determined. So far inheriting from std::unique_ptr, inheriting its constructors, and declaring an implicit conversion operator has worked splendidly with hardly any code needing to be written.
Am I just going to have to live without this the rest of my life?Answer-So-Far: We'll see...If I can get option 2 up and running without any serious side-effect or burdens, I'll test it out for a while and report back on whether I think it's worth it. We'll see!
Example code:
#include <algorithm>
#include <memory>
#include <vector>
struct MyClass
{
MyClass(int v) : value(v) {}
int value;
};
int main()
{
auto vec = std::vector<std::unique_ptr<MyClass>>();
vec.push_back(std::make_unique<MyClass>(1));
vec.push_back(std::make_unique<MyClass>(2));
// error C2664: 'void (__vectorcall *)(MyClass *)' : cannot convert argument 1 from 'std::unique_ptr<MyClass,std::default_delete<_Ty>>' to 'MyClass *'
std::for_each(std::begin(vec), std::end(vec), [](MyClass* myClass)
{
myClass->value += 3;
});
}
If you don't want to use std::unique_ptr<>::get() function, you can:
Define a free function that takes a std::unique_ptr and returns the raw pointer returned by get, although I don't think it really makes your code better, like:
// free function
template<typename T>
T* get_raw_ptr(const std::unique_ptr<T>& up)
{
return up.get();
}
Conversions of unique_ptr to raw pointers are OK, but they have to be explicit. Implicit conversion may lead to lots of headaches, since they may happen when you least expect them.
It is a bad idea to derived from std::unique_ptr, as the latter is not made to be used as a base class (doesn't have a virtual destructor). In general, it is bad to derive from Standard Library classes. However, if you really insist, you can use a wrapper in which you define the implicit conversion operator, like:
// wrapper
template <class T, class Deleter = std::default_delete<T>>
class unique_ptr_wrapper: public std::unique_ptr<T, Deleter>
{
public:
using std::unique_ptr<T, Deleter>::unique_ptr; // inheriting base ctors
operator T* () const {return this->get();}
};
and use is simply like
// wrapper usage:
unique_ptr_wrapper<int> upw{new int{42}};
int* p = upw; // implicit conversion OK
1 and 2 can help you, so you may improve your life ;)

Un-inherit from std::basic_string

Basically, I have a large project that uses a custom utility class c_string that inherits from std::basic_string<char>. For numerous reasons, I would like to edit this class so that
It does not derive from std::basic_string<char>
I do not have to re-implement all the functions
I do not have to touch every file that uses c_string
So I want to change from:
class c_string : public std::basic_string<char>
{
public:
typedef std::basic_string<char> Base;
c_string() : Base() {}
}
To:
class c_string
{
...
public:
...
c_string() {...}
}
So, I'm wondering if anyone has a good strategy for making this change with minimal impact.
If your class adds custom functionality (that your project needs) over std::string, then you're out of luck: you will either have to encapsulate std::string (and implement all methods to forward to std::string implementation) or inherit from std::string (inheriting from std::string is not a good idea in general).
If your class doesn't add extra functionality over std::string, then replace class c_string { ... } with typedef std::string c_string;.
There is another thing you can do and that is to change the public inheritance with private inheritance. Doing that, you will get a bunch of compile errors, because all of string's memberfunctions are now private to the clients of your class. You can then selectively make these public:
class my_string: std::string {
public:
typedef std::string base; // convenience
using base::const_iterator;
using base::begin;
using base::end;
};
You should understand private derivation not as "my_string is a std::string" but "my_string is implemented in terms of std::string". This technique avoids some of the downsides (implicit conversion, slicing etc) of deriving from a type that is not intended to be a baseclass, like std::string. Doing this conversion is easy, it's just work with little risk of breaking anything. Afterwards though, you have control over the forwarded interfaces, which makes conversion and refactoring much easier.
I can't see any way that you could avoid at least wrapping all the functions. The most straightforward way would be to have a private basic_string member, and just write wrappers that call the same function on that member.
I have nearly the same problem as zdp. Not inherit from std::string leads in a lot of code not to use methods (we have a lot like this) as void Foo(string &s_) where a string is the parameter in the function and the user puts a my_string to Foo(). In short therm: Inherit from std::string and you can send your my_string to any function which takes a my_string OR a std::string as parameter.
I would like to rewrite my my_string class but there are a lot of code with this problem in other hands and a lot of people have to change their code too.
One bad choice 14 years ago....... sh..

Problems with stream interface in C++

So I have a virtual streaming interface in c++
class KxStream
{
public:
virtual KxStream& operator<< ( u32 num ) = 0;
};
It has a ton of basic << operators for all the built-in types. I've just listed one.
Then I have a few classes that implement the streaming interface. Like this:
class KxCbuf : public KxStream
{
public:
KxStream& operator<<( u32 num );
}
So there is an implementation of the streaming interface in KxCbuf. So far so good. Then I have some classes that overload the stream interface:
class KxSymbol
{
operator u32() const;
friend KxStream& operator<<( KxStream& os, KxSymbol sym );
};
Note that this class has cast operator to a built-in type. Now when I try to stream one of these classes into one of the classes that implements the streaming interface I get an error:
KxCbuf buf;
KxSymbol sym;
buf << sym; // error!
The compiler gets confused about which functions to use. Gcc compiles fine, but says that there are multiple ways do this this. MSVC does not compile saying there are multiple overloads:
src/variable.cpp(524) : error C2666: 'KxCbuf::operator <<' : 15 overloads have similar conversions
I know what is happening, just not how to solve it satisfactorily. So the compiler can either cast KxCbuf -> KxStream, and then call the friend function, which is the right thing to do. Or it can cast KxSymbol -> u32, and then call the u32 << operator in KxCbuf, inherited from KxStream.
I can solve it two (bad) ways.
I can start by streaming in something unambiguous:
buf << "" << sym;
This way the return value of the first stream operator for "" return KxStream, and all is well. Or I can implement a redundant stream operator for the implementation class. E.g. I can add the following to KxSymbol:
friend KxStream& operator<<( KxCbuf& os, KxSymbol sym );
The first answer always works - but it sure is ugly. The second answer is also ugly, in that I have to create redundant stream operators, and does not always work in that the KxStream implementations are not always visible in places where I need to define new stream operators.
Ideally I'd like implementations of the KxStream interface to work just like KxStream objects, and avoid implicit casts that cause ambiguous conversions.
How do I solve this?
(ps. I need to create my own streaming operators for a custom serialization scheme for my library. I can't use boost or similar third party libraries that have their own serialization classes )
#Edit: There are several good answers related to controlling the compiler's use of the implicit conversion, like the conversion to KxSymbol -> u32, unfortunately that implicit conversion is important to the code. For example KxSymbol is a class that stores strings in a table and returns them as numbers so that I can compare strings as numbers. E.g. if two symbols are not equal, then the strings are not the same. I also store symbols as numbers in some data structures.
Is there a way to solve this from the other side, somehow make the compiler understand that implementations of KxStream should be cast to KxStream objects by preference to other implicit casts?
For example what if I would somehow force the compiler to have to first cast KxCbuf to KxStream before using the operator<< for the built-in types. This would make it always prefer the overload operator<<'s over the KxStream ones. - the overloads would require one cast, and the KxStream ones would require two.
If you have a C++11 compiler, mark the conversion function "explicit". That way you won't get implicit conversions to u32, and this sort of ambiguity will disappear.
The simplest and safest way is to change your implicit conversion from operator u32() const; to a named method u32 as_u32() const. Not only does this remove the ambiguity it can prevent all sorts of unwanted accidental conversions that will get you in trouble in the future.
I think I may have an answer. Implement the built-in stream operators in virtual private methods.
So I do something like this:
class KxStream
{
public:
KxStream& operator<< ( u32 num ) { return stream_i( num ); }
private:
virtual KxStream& stream_i ( u32 num ) = 0;
};
class KxCbuf : public KxStream
{
private:
KxStream& stream_i( u32 num );
}
Now there is no way for the compiler to call the built-in operator<< through KxCbuf. It can only use the public methods in KxStream. But I still get the virtual method overloads through the private stream_i methods. So when streaming to KxCbuf, the compiler must always cast to KxStream. Its the only way.
When deciding between the friend overloads, and the built-ins, the friend overloads win because the built-ins require 2 casts and the overloads require one.

How to add a custom implicit conversion to a C++ type in Boost::Python?

In my C++ code I have a class Foo with many methods taking a Bar type variable as an argument:
class Foo {
public:
void do_this(Bar b);
void do_that(Bar b);
/* ... */
};
Bar has a number of constructors that create a new object from many common types such as int, std::string, float, etc:
class Bar {
public:
Bar(int i);
Bar(float f);
Bar(std::string s);
/* ... */
};
I wrapped this with Boost::Python and I'm now able to call my Foo methods using Python literals directly, as they get implicitly converted to Bar objects.
f = Foo()
f.do_this(5)
f.do_that("hello")
Now, I would like to be able to use also other Python types, such as tuples, like this:
f.do_that((1,2,3))
But I don't want to touch the original Bar definition, and I don't want to pollute my C++ library with Boost::Python stuff. I want to write a wrapper function in my binding code, but I just can't understand if this is possible and what is the correct way for doing this.
In other words: can I register a factory function to be used as an automatic conversion in Python?
Subclass Bar near the wrapper code and give your subclass a ctor that takes a bp::object (or a more specific python type)
struct Bar_wrapper:Bar,bp::wrapper<Bar>
{
Bar_wrapper(bp::object arg)
{
//code to build a Bar_wrapper Here
}
}
Then export a Bar_wrapper to python instead of a Bar, and call it a Bar as the python name:
class<Bar_wrapper>("Bar")
...
.def(init<bp::object>())
...
Add a new constructor template <typename T> Bar(T)
in your header and implement as template <>
Bar::Bar(Tupple) {}
Create some type TupleCollector with overridden "operator ,(int)" so you can write
f.do_that((TuppleCollector(), 1, 2, 3))
at last create conversion between TupleCollector and expected target
You can make a static factory method and then expose it as one of the Python constructors for the class. Just make a converter that will take any Python object and you're free do do whatever your please.
using namespace boost::python;
Bar CreateBar(object obj)
{
// Do your thing here
return Bar;
}
// ..................
class_<Bar>("Bar")
// .....................
.def("__init__", make_constructor(&CreateBar))
//.............
;
You can register from-python converter which will construct Bar instance from arbitrary object. See here and an exmaple of my own (converts either (Vector3,Quaternion) tuple or 7*double-tuple to 3d transformation Se3) here.
Note that the logic has two steps, first you determine whether the object is convertible (convertible; in your case, you check that it is a sequence, and has the right number of elements), then the construct method is called, which actually returns the instance, allocated with the pointer passed as parameter.
The converter must then be registered in BOOST_PYTHON_MODULE. Since the converter registry is global, once registered, it will be subsequently used automatically everywhere. All function argument of type Bar or const Bar& should be handled just fine (nor sure about Bar& from the top of my head).
You can export function do_that which take boost::python::object param, check if param is a python tuple, extract data and pass it to object.

User-defined cast to string in C++ (like __repr__ in Python)

How do I make something like user-defined __repr__ in Python?
Let's say I have an object1 of SomeClass, let's say I have a function void function1(std::string). Is there a way to define something (function, method, ...) to make compiler cast class SomeClass to std::string upon call of function1(object1)?
(I know that I can use stringstream buffer and operator <<, but I'd like to find a way without an intermediary operation like that)
Define a conversion operator:
class SomeClass {
public:
operator std::string () const {
return "SomeClassStringRepresentation";
}
};
Note that this will work not only in function calls, but in any context the compiler would try to match the type with std::string - in initializations and assignments, operators, etc. So be careful with that, as it is all too easy to make the code hard to read with many implicit conversions.
Use a conversion operator. Like this:
class SomeClass {
public:
operator string() const { //implement code that will produce an instance of string and return it here}
};