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.
In a module called State, we have an abstract type t. We're now trying to make an entirely separate module which contains a function that takes in a State.t (its type starts with State.t -> (* stuff *)).
However, when we try to call that function from within our State module, passing in an object of type t, we get the following error:
Error: This expression has type t but an expression was expected of type State.t
State.t is abstract because no corresponding cmi file was found in path.
We assume this is happening because the other module is expecting an abstract type, but from inside the State module, the abstract type is concrete. Our question is, how do we make that object abstract again so that we can pass it into the other module?
I have two derived types (child1 and child2) that both extend from the same abstract type (type, abstract :: parent). The abstract type has a deferred bound procedure.
I want to call a subroutine that performs some stuff (performance critical) depending on the type of the child handed over as input. I can think of two options:
The subroutine takes the class(parent), intent(inout) :: type_in as input. Implementations for the children are then done within a select type (type_in) construct.
I write two subroutines, one with type(child1), intent(inout) :: type_in and one with type(child2), intent(inout) :: type_in and provide an explicit interface to overload the routine name.
The first option allows for implementations where the extension of the parent is not known at compile time, but that is not necessary in my case. It also saves some lines of code because only a part of it is different for the children.
My question is: Is there additional overhead in option one because I implemented the input as polymorphic data when the type is known at compile time?
Yes, there is additional cost of a so call virtual call. A virtual method table (as it is called in other languages) is used and searched for the right procedure to call. The cost is likely to be similar to that of a virtual function call in C++, see https://stackoverflow.com/a/453001/721644
The compiler is sometimes able to find out which procedure is called by the binding even at compile time. For example, when the actual passed object is non-polymorphic. GCC has two flags -fdevirtualize and -fdevirtualize-speculatively (enabled with -O2, -O3, -Os) which convert virtual calls to direct calls. They are likely applicable to Fortran too.
I am writing a class Base which has a member function taking a template parameter:
class Base {
template<class T>
void func(const T& t) { ... }
};
There's a class Derived which conceptually inherits natures of Base and has the same function func with different implementation.
At first I thought of deriving Derived from Base and make func virtual, but I can't because it's template.
I also thought of CRTP, but it's an option because instances must be able to put into a container and be accessible without knowing exact types of them:
std::vector<Base*> v = ...;
v[0]->func(...);
v[1]->func(...);
Overloading for possible types of T is also not an option.
What is the best solution to this situation?
And aside from the topic, would you recommend references (preferably books) for such kind of problems?
You cannot mix compile time polymorphism (templates) with runtime polymorphism like that. The problem is that with a template, the compiler will generate the code on-demand when it is used, and in your particular case, you want to decide what member function to instantiate based on the runtime type of the object in the vector.
If the number of types that can be used with the methods is limited, you can provide different virtual overloads, if you don't want to do that manually, you can probably define a type list with all of the types T, and then use that typelist to generate the methods... but that will be awful to code and maintain.
I recommend that you state the actual requirements of the problem (rather than the requirements of your proposed solution), and people will be able to provide alternative approaches.
This is not something easily done with C++. It's related to something called "first class polymorphism", which means it would be easy if the values in C++ could have polymorphic types. This is not the case.
If you'll be fine with a generic solution (that means the code f must be the same for all T), you can maybe do it, but it will be a laborious task.
Basically, you'll want to replace your const T &t parameter with a parameter whose type that wouldn't be generic, but will capture "inside" all the behaviour f needs from ts of all possible types.
For an example, let's say T is meant to be a functor, that f calls with an int argument. In this case, you'll change the declaration to
virtual void func(const std::function<void(int)>& t) { ... }
and virtual functions will start to work. However, that means the interface of Ts will have to be fixed before you start to implement it in derived classes (meaning if you change your mind and want to call t with an argument of type ostream, you're out of luck).
However, creating such polymorphic wrappers ranges from easy (as is boost::any, boost::function) to hard or even impossible (any_iterator). It's very dependent on what you want to do.
I created this .h file
#pragma once
namespace Core
{
class IComparableObject
{
public:
virtual int CompareTo(IComparableObject obj)=0;
};
}
But compiler doesn't like IComparableObject obj param if the method is virtual pure, while
virtual int CompareTo(IComparableObject obj) {}
It's ok, however I want it as virtual pure. How can I manage to do it? Is it possible?
You are trying to pass obj by value. You cannot pass an abstract class instance by value, because no abstract class can ever be instantiated (directly). To do what you want, you have to pass obj by reference, for example like so:
virtual int CompareTo(IComparableObject const &obj)=0;
It works when you give an implementation for CompareTo because then the class is not abstract any longer. But be aware that slicing occurs! You don't want to pass obj by value.
Well I have to give an unexpected answer here! Dennycrane said you can do this:
virtual int CompareTo(IComparableObject const &obj)=0;
but this is not correct either. Oh yes, it compiles, but it is useless because it can never be implemented correctly.
This issue is fundamental to the collapse of (statically typed) Object Orientation, so it is vital that programmers using OO recognize the issue. The problem has a name, it is called the covariance problem and it destroys OO utterly as a general programming paradigm; that is, a way of representing and independently implementing general abstractions.
This explanation will be a bit long and sloppy so bear with me and try to read between the lines.
First, an abstract class with a pure virtual method taking no arguments can be easily implemented in any derived class, since the method has access to the non-static data variables of the derived class via the this pointer. The this pointer has the type of a pointer to the derived class, and so we can say it varies along with the class, in fact it is covariant with the derived class type.
Let me call this kind of polymorphism first order, it clearly supports dispatching predicates on the object type. Indeed, the return type of such a method may also vary down with the object and class type, that is, the return type is covariant.
Now, I will generalise the idea of a method with no arguments to allow arbitrary scalar arguments (such as ints) claiming this changes nothing: this is merely a family of methods indexed by the scalar type. The important property here is that the scalar type is closed. In a derived class exactly the same scalar type must be used. in other words, the type is invariant.
General introduction of invariant parameters to a virtual function still permits polymorphism, but the result is still first order.
Unfortunately, such functions have limited utility, although they are very useful when the abstraction is only first order: a good example is device drivers.
But what if you want to model something which is actually interesting, that is, it is at least a relation?
The answer to this is: you cannot do it. This is a mathematical fact and has nothing to do with the programming language involved. Lets suppose you have an abstraction for say, numbers, and you want to add one number to another number, or compare them (as in the OP's example). Ignoring symmetry, if you have N implementations, you will have to write N^2 functions to perform the operations. If you add a new implementation of the abstraction, you have to write N+1 new functions.
Now, I have the first proof that OO is screwed: you cannot fit N^2 methods into a virtual dispatch schema because such a schema is linear. N classes gives you N methods you can implement and for N>1, N^2 > N, so OO is screwed, QED.
In a C++ context you can see the problem: consider :
struct MyComparable : IComparableObject {
int CompareTo(IComparableObject &other) { .. }
};
Arggg! We're screwed! We can't fill in the .. part here because we only have a reference to an abstraction, which has no data in it to compare to. Of course this must be the case, because there are an open/indeterminate/infinite number of possible implementations. There's no possible way to write a single comparison routine as an axiom.
Of course, if you have various property routines, or a common universal representation you can do it, but this does not count, because then the mapping to the universal representation is parameterless and thus the abstraction is only first order. For example if you have various integer representations and you add them by converting both to GNU gmp's data type mpz, then you are using two covariant projection functions and a single global non-polymorphic comparison or addition function.
This is not a counter example, it is a non-solution of the problem, which is to represent a relation or method which is covariant in at least two variables (at least self and other).
You may think you could solve this with:
struct MyComparable : IComparableObject {
int CompareTo(MyComparable &other) { .. }
};
After all you can implement this interface because you know the representation of other now, since it is MyComparable.
Do not laugh at this solution, because it is exactly what Bertrand Meyer did in Eiffel, and it is what many people do in C++ with a small change to try to work around the fact it isn't type safe and doesn't actually override the base-class function:
struct MyComparable : IComparableObject {
int CompareTo(IComparableObject &other) {
try
MyComparable &sibling = dynamic_cast(other);
...
catch (..) { return 0; }
}
};
This isn't a solution. It says that two things aren't equal just because they have different representations. That does not meet the requirement, which is to compare two things in the abstract. Two numbers, for example, cannot fail to be equal just because the representation used is different: zero equals zero, even if one is an mpz and the other an int. Remember: the idea is to properly represent an abstraction, and that means the behaviour must depend only on the abstract value, not the details of a particular implementation.
Some people have tried double dispatch. Clearly, that cannot work either. There is no possible escape from the basic issue here: you cannot stuff a square into a line.
virtual function dispatch is linear, second order problems are quadratic, so OO cannot represent second order problems.
Now I want to be very clear here that C++ and other statically typed OO languages are broken, not because they can't solve this problem, because it cannot be solved, and it isn't a problem: its a simple fact. The reason these languages and the OO paradigm in general are broken is because they promise to deliver general abstractions and then fail to do so. In the case of C++ this is the promise:
struct IComparableObject { virtual int CompareTo(IComparableObject obj)=0; };
and here is where the implicit contract is broken:
struct MyComparable : IComparableObject {
int CompareTo(IComparableObject &other) { throw 00; }
};
because the implementation I gave there is effectively the only possible one.
Well before leaving, you may ask: What is the right way (TM).
The answer is: use functional programming. In C++ that means templates.
template<class T, class U> int compare(T,U);
So if you have N types to compare, and you actually compare all combinations, then yes indeed you have to provide N^2 specialisations. Which shows templates deliver on the promise, at least in this respect. It's a fact: you can't dispatch at run time over an open set of types if the function is variant in more than one parameter.
BTW: in case you aren't convinced by theory .. just go look at the ISO C++ Standard library and see how much virtual function polymorphism is used there, compared to functional programming with templates..
Finally please note carefully that I am not saying classes and such like are useless, I use virtual function polymorphism myself: I'm saying that this is limited to particular problems and not a general way to represent abstractions, and therefore not worthy of being called a paradigm.
From C++03, ยง10.4 3:
An abstract class shall not be used as a parameter type, as a function return type, or as the type of an explicit conversion. Pointers and references to an abstract class can be declared.
Passing obj as a const reference is allowed.
When the CompareTo member function is pure virtual, IComparableObject is an abstract class.
You can't directly copy an object of an abstract class.
When you pass an object by value you're directly copying that object.
Instead of passing by value, you can pass by reference to const.
That is, formal argument type IComparableObject const&.
By the way, the function should probably be declared const so that it can be called on const object.
Also, instead of #pragma once, which is non-standard (but supported by most compilers), consider an ordinary include guard.
Also, when posting code that illustrates a problem, be sure to post exact code. In this case, there's a missing semicolon at the end, indicating manual typing of the code (and so that there could be other typos not so easily identified as such, but instead misidentified as part of your problem). Simply copy and paste real code.
Cheers & hth.,