I am using a library that has some useful types but they are missing some functionality. I am thus thinking if there is a good way to extend these types.
I have taken some other types from the library, inherited from them and just used my own expanded versions. I can't think of a way to make this work for the following issue.
There is a floating point and an integral 2D point struct, i.e. Point2D and Point2DInt. I would like to be able to either implicitly convert between the two or be able to construct one from the other, in either case I want to add a constructor to this external class.
There is a float to int constructor in the integral class but none that goes the other way.
I understand that I could just make a utility function to do this but would like to know if this is possible in general.
The only way of making a class implicitly convertible to another is to modify one of the classes (either add converting constructor to one, or conversion operator to another). The modification has to be in the definition of the class; not after the definition.
Indeed, you can write a function that takes one as an argument and returns the other, but the implicit conversion is not possible.
Related
Recently I have to work with some C libraries in my C++ code. The C library I am using defined a complex number class as follow:
typedef struct sfe_complex_s
{
float real;
float img;
} sfe_complex_t;
Naturally I do not want to work with this C-style data structure in C++, so for convenience I want to define an implicit conversion from this type to std::complex<float>. Is there a way to do so? Or I have to explicitly do the conversion?
Implicit conversion is supposed to mean something. It represents a strong relationship between the source and destination types of that conversion. That one of them is, on some level, designed to be equivalent to another in some degree.
As such, only code which is intimately associated with either the source or destination type can define that relationship. That is, if you don't have control over the source or destination types, then C++ doesn't feel that you are qualified to create an implicit conversion relationship between them.
3rd parties cannot make types implicitly convertible.
An implicit conversion can only take place in a constructor of the class converted to or a conversion operator of the class converted from, which has to be a member function. Since you cannot modify either one, you are out of luck.
It may be appealing to define an own class with implicit constructors from and conversion operators to both std::complex<float> and sfe_complex_t, but this will not give you implicit conversions between these two clases, since user defined conversions cannot be chained. You could a class defined in this way in your code and it would always be converted implicitly if you put it somewhere either of the others are expected, but you should really consider if that is what you want. It would introduce another standard and make your code less readable.
To me, it seems like calling an explicit conversion is the cleanest variant. Depending on the number of functions of your C library you could perhaps for each one provide an overload taking std::complex and explicitly converting it before passing it on.
No, you cannot define an implicit conversion between types that you don't have access to change. Your only option will be to define your own function that explicitly takes a sfe_complex_t as input and returns a std::complex<float> as output.
I'm using two independent third party libraries in my C++ project (Qt, cocos2d). Both define their own version of 2d and 3d vectors. How could I implement custom implicit (or explicit) conversion methods, so that I don't have to explicitly create new instances like this:
// mousePosition is of type QPointF
auto position = cocos2d::Vec2(mousePosition.x(), mousePosition.y())
Of course I cannot really modify the source of either library. In Obj-C or C# I could use class extensions. I'm not sure about C++. Is there any better solution than plain global functions?
There’s no way to implement an implicit conversion between two types without altering either of them. This can be explained mechanically: such a conversion would have to be a constructor or a conversion operator, both of which must be members.
The more enlightening explanation is that such an implicit conversion could break existing use of the types (e.g., by introducing ambiguity). With templates, it can easily be undefined behavior to introduce additional overloads (or, in this hypothetical case, make more viable) after the template is defined.
So your conversion must be explicit, and then it’s trivial: define
B convert(const A&);
A convert(const B&);
for as many A-B pairs as necessary; conveniently, they need not even have different names, since by hypothesis there is no implicit conversion between them.
I want to overload "->" operator globally for pointers. Is it possible?
A *var1 = new A(21);
int x = var1->someInt;
In that code it has to be triggered when reaching "var1"s "someInt" variable.
Actually I am trying to check the pointer before reaching its members. Also, I am trying to implement this system on a written code, so I don't want to change too much thing in the actual code.
I want to overload "->" operator globally. Is it possible?
No it is impossible.
Perhaps you might define a "root" class in your library or program (which would define that operator ->), and have all your classes inherit from it.
BTW, I am not sure you will be able to define your isPointerValid function in all cases (including the address of valid automatic variables of any class type), and efficiently.
There are many cases where you could not define such a function (e.g. union-s used in tagged union types; you don't easily know what member of a union is currently active. arbitrary casts; ...); .
For existing code and classes, the builtin meaning of -> (which you usually cannot redefine) has already been used to compile the code using them.
As described in C++17 standard draft in section 16.5.6 (emphasis mine):
An operator function shall either be a non-static member function or
be a non-member function that has at least one parameter whose type
is a class, a reference to a class, an enumeration, or a reference to
an enumeration.
Hence, it is not possible to overload an operator which doesn't take any arguments.
I was wondering if there is a difference between the methods of conversion, and if one is better than the other.
Suppose there is a class A and a class B. class B can be converted to a class A. Say for example class A is something representing a string, and class B is something representing an integer.
You could obtain a class A object from a class B object in a number of ways:
operator A() function in class B to allow implicit conversion
explicit operator A() function in class B to allow explicit conversion
A toA() function in class B, to effectively convert it
static A parse(B) function in class A to convert it
A(B) constructor in class A to create a new object
Is there any preferred way of converting the object? Should multiple ways be implemented? Should any be avoided? Or is it all context-based, and should it be determined by best judgment?
It's been a while since I posted this question and since then I've developed a few guidelines which I try to stick by in my projects, and I thought I'd share them so others who stumble upon this question can benefit from them as well.
I also welcome any input on the drawbacks of these guidelines, as they are probably not perfect.
An object should only provide implicit conversion constructors for objects that are directly related to that class in some way. For example, a string class that offers a constructor that accepts a char array. When the conversion is lossy, or the classes are unrelated, use an explicit conversion constructor.
An object should only provide implicit conversion operators to objects it is directly related to and for conversions which are lossless (no information is lost). Again, a string can provide a conversion to a character array. If this is not the case, an explicit conversion operator should be used.
Provide toX() functions for all conversion operators (implicit and explicit). This isn't really a strict guideline, but more personal preference. Sometimes it is better to write toX() in your code as it conveys your intent better, in my opinion.
Only use parse(X) functions if the function has to be static for some reason.
Free functions can be used as an alternative to a parse(X) function, this depends on personal preference.
As I said, I welcome any input and I hope this may help someone.
Suppose there're two types:
typedef unsigned short Altitude;
typedef double Time;
To detect some errors like passing time argument in position of altitude to functions at compile time I'd like to prohibit implicit conversion from Altitude to Time and vice-versa.
What I tried first was declaring an operator Altitude(Time) without an implementation, but the compiler said that it must be a member function, so I understood that it's not going to work for a typedefed type.
Next I've tried turning one of these types into a class, but it appeared that the project extensively uses lots of arithmetic including implicit conversions to double, int, bool etc., as well as passes them to and from streams via operator<< and operator>>. So despite this way allowed me to find the errors I was looking for, I didn't even try to make full implementation of the compatible class because it would take a lot of code.
So my question is: is there a more elegant way to prevent implicit conversions between two particular typedefed types, and if yes, then how?
A typedef does nothing more than establish another name for an existing type.
Therefore your question boils down to whether you can disable implicit conversions between unsigned short and double, which is not possible in general.
Two ways exist to deal with this problem:
First, you can make Altitude and Time into their own types (read: define classes instead of typedefs) and ensure that they can be easily converted to and from their underlying numeric types - but not each other.
Second, you can ensure that whatever you do is protected by language constructs, e.g. if you have a function f that should take an Altitude a.k.a. unsigned short, you can overload it with another function f that takes an Time a.k.a. double and causes an error. This provides a better overload match and would thus prevent the implicit conversion in that case.