So, I have a single templated class, B, which inherits from a non-template class A. Now, this templated version B, has a set of four valid and known template classes, call them B<uint8_t>, B<uint16_t>, B<uint32_t>, B<uint64_t>.
Currently, I am storing these in a map, boost::unordered_map<std::string, A>, and I would like to create some way to cast to the different types. I can easily differentiate based on a A::width() method which returns 8, 16, 32, or 64 respectively.
I have been racking my brain for a good design but I can't figure out a way to get a better solution than having every use casting themselves.
Here is a minimum working case:
class A {
std::size_t width() const = 0;
};
template <typename value> class B : public A {
std::size_t width() const {
return sizeof(value) * 8;
}
};
Within usage:
boost::unordered_map<std::string, A *> _bmap;
template <class T> T cast_A(A * const a) {
switch (a->width()) {
case 8: return dynamic_cast<B<uint8_t> *>(a);
// removed for brevity
}
The problem with this is that it forces the user to check the runtime type of the A class after, aka making the cast method absolutely useless.
I welcome any input. :)
You could use, e.g., a templated get() method which converts to the asked for size via a virtual method going through the largest supported type. If the conversion would loose bits (checked at run-time) you could produce an error.
I think the downcasting is not very good idea in this case. It seems to be a design problem.
However, you could try to implement something like visitor pattern for these classes. It may solve your problem, but I'm not sure, because there are no use examples of B objects.
Related
I'm pushing IMO the limits of C++template programming. The system is an Arduino but my attempt is applicable to any microcontroller system.
I define Pins using a template class with an 'int' parameters
template<const int pin>
struct Pin {
Pin() { mode(pin, 0); }
};
template<const int pin>
class PinOut : public Pin<pin> {};
I can create template classes to use PinOut like:
template<typename F>
class M {
public:
M() { }
F mF;
};
M<PinOut<1>> m1;
template<int F>
class N {
public:
N() { }
Pin<F> mF;
};
N<1> n1;
But I'd like to not use templates in the classes that use PinOut. This is illustrative of my thinking showing possible approaches but clearly doesn't work.
class R {
public:
R(const int i) {
}
PinOut<i> mF; // create template instance here
};
R r1(1); // what I'd like to able to do
I recognize the problem is creating a type inside class R.
The other possibility is instantiating a PinOut variable and passing it in but again passing and creating a type inside the class is a problem. Something like this:
class S {
public:
S(PinOut<int>& p) { } // how to pass the type and instance
PinOut<p>& mF; // and use it here
};
PinOut<1> pp;
S s1(pp);
Sorry if this sound abrupt but please don't ask why or what I'm trying to do. This is an experiment and I'm pushing my understanding of C++ especially templates. I know there are other approaches.
Yes, any function that takes that type must itself be a template.
But is the entire family of Pin related in a way that some thing are meaningful without knowing T? This can be handled with a base class that's a non-template. The base class idea is especially handy because it can contain virtual functions that do know about T. This lets you switch between compile-time and run-time polymorphism on the fly as desired. Taken to an extreme, that becomes the weaker idea with the same syntax of "Generics" as seen in Java and .NET.
More generally, this is a concept known as type erasure. You might search for that term to find out more. It is designed into libraries in order to keep common code common and prevent gratuitous multiplication of the same passage though multiple instantiations.
In your case, pin is a non-type argument, which is something Generics don't even do. But it may not really affect the type much at all: what about the members change depending on pin? This might be an array bound, or a compile-time constant used to provide compile-time knowledge and optimization, or there for the sole purpose of making the type distinct.
All of these cases are things can be dealt with at run-time, too. If it's for the sole purpose of making the type distinct (e.g. make the compiler check that you pass time values and distance values to the correct parameters) then the real guts are all in a base class that omits the distinctiveness.
If it's an array bound or other type difference that can be managed at run-time, then again the base class or an adapter/proxy can do it at run-time. More generally a compile-time constant that doesn't affect the class layout can be known at run-time with the same effect, just less optimization.
From your example, that it is sensible to make the pin a constructor argument, the class could be implemented in the normal way with run-time configuration. Why is it a template? Presumably for compile-time checking to keep separate things separate. That doesn't cause them to work in different ways, so you want that compile-time part to be optional. So, this is a case where a base class does the trick:
class AnyPin
{
public:
AnyPin (int pin); // run-time configuration
};
template <int pin>
class Pin : public AnyPin { ⋯ };
Now you can write functions that take AnyPin, or write functions that take Pin<5> and get compile-time checking.
So just what does pin do to the class, in terms of its layout and functionality? Does it do anything that makes it unacceptable to just implement it as a run-time constructor value?
You ask that we don't inquire as to what you're trying to do, but I must say that templates have certain features and benefits, and there must be some reason for making it a template. Speaking simply in language-centric terms, did I miss something with the above analysis? Can you give a C++-programming reason for wanting it to be a template, if my summary didn't cover it? That may be why you didn't get any answers thus far.
I am working on a fairly tightly coupled library which up until now has explicitly assumed all computations are done with doubles. I'm in the process of converting some of the core classes to templates so that we can start computing with std::complex<double>. I've templated about 10 of our classes so far have noticed a tendency toward proliferation of templates. As one class becomes templated, any other class that uses the templated class appears to need templating as well. I think I can avoid some of this proliferation by defining abstract base classes for my templates so that other classes can just use pointers to the abstract class and then refer to either a double or std::complex<double> version of the derived class. This seems to work on at the header level, but when I dive into the source files, the templated class will often have functions which compute a value or container of values of type double or std::complex<double>. It seems like a waste to template a whole class just because a couple of lines in the source file are different because of some other classes return type.
The use of auto seems like a possible way to fix this, but I'm not 100% sure it would work. Suppose I have an abstract base class AbstractFunction from which Function<Scalar> derives, where Scalar can be double or std::complex<double>. Now suppose we have two member functions:
virtual Scalar Function<Scalar>::value(double x);
virtual void Function<Scalar>::values(std::vector<Scalar> &values, std::vector<double> x);
And suppose I have some other class (that I don't want to template) with a member function that calls one of these.
// populate double x and std::vector<double> xs
auto value = functionPtr->value(x);
std::vector<auto> values;
functionPtr->values(values, xs);
// do something with value and values
where functionPtr is of type std::shared_ptr<AbstractFunction>.
I could see auto working for the first case, but I don't believe I could construct a vector of auto to be filled with the second one. Does this necessitate making the calling class a template? Can someone recommend another strategy to cut down on the proliferation of templates?
I think you are already wrong in assuming that the first use-case is going to work. If you have an abstract base class, then either value is a member of it and you can call it through std::shared_ptr<AbstractFunction> or value is not a member of it and only available if you know the derived class' type. In the first case, the AbstractFunction::value method must have a fixed return type, it can not depend on Scalar, which is the template parameter of the derived class.
That said: In my experience the two concept often don't mix well. You either want to create an abstract base class with the full interface or you want a template. In the latter case, there is often no need / no benefit for having an abstract base class. It then follows that also the code using your template works with templates.
What might help you is to "export" the template parameter from Function, i.e.
template<typename T>
class Function
{
public:
using value_type = T;
value_type value() const;
// ...
};
and in other parts of the code, use a template which takes any T which behaves like Function if you don't want to directly write out (and limit yourself) to Function:
template<typename T>
void something( const std::shared_ptr<T>& functionPtr )
{
// ignoring where x comes from...
using V = typename T::value_type;
V value = functionPtr->value(x);
std::vector<V> values;
functionPtr->values(values, xs);
}
Note that this is just one option, I don't know if it is the best option for your use-case.
I have got two classes.
The first class (A) is builded with an template.
template <class T>
class A
{
public:
T value;
};
The second class (B) should have an object of class A as member variable. Like this:
class B
{
public:
A<int> value;
};
But now i want to use any kind of template-class in class A. Not only int.
Apparent I can't declare a (member-)variable which contains any kind of a class.
So, I need something like this:
class B
{
public:
A<*> value;
};
Is there any (clean) solution for this problem?
-- Greeting from Germany, Bastian
You cannot have a single class B with "any" member object, because B has to be a well-defined class, and A<T> is a different type for different types T. You can either make B a template itself:
template <typename T>
class B
{
A<T> value;
};
or you can take a look at boost::any, which is type-erasing container for arbitrary types (but making use of it requires a certain amount of extra work). The any class only works for value types, though, it's not completely arbitrary.
The simplest solution would be to make all A variants ineherit from a common interface, even if it's empty :
class IA{}
template <class T>
class A : public IA
{
public:
T value;
};
class B
{
public:
IA* value;
};
Now, the associated costs:
interactions with value are limited to the IA interface;
if you try to cast to get the real type, that mean that you know the real type, so it's of no use and make A type a parameter of B becomes really easier to use.
there are runtime costs associated to runtime inheritance
Advantage :
it's easily understood by other developers
it naturally limit the types possible to some specific ones
it don't use boost (sometimes, you just can't)
So to do better there are other less simple solutions but that are simple enough to be used :
If you can use boost, boost::any, boost::variant and boost::mpl might be base of solutions.
Boost any can be used as a safe replacement to void*. The only problem with this is that you can have ANY type, like if the type was a template parameter of the B class.
Boost variant might be used successfully if you know all the types that A can be.
MPL might be helpful if you just want to set a list of possible types and make sure your members apply only to them. You can do a ton of things with MPL so it really depends on your exact needs.
You've got two choices, I think. The first is to parameterize your class over the type parameters of the instance variables:
template <class T> struct B
{
A<T> value;
};
The other option is to declare value as a void* pointer. (But that's probably not what you want).
yes, it's already been done. boost::any.
I think it helps to understand, that templated classes create an entirely new and seperate class for every type you use with it. For instance, Vector<int> and Vector<float> are as separate as the classes VectorInt and VectorFloat.
For class B, you are basically asking that the value variable either be A<int> or A<float>, which is the same as saying you want value to either be a "A_int" or "A_float". And to accomplish that you... well, use another template!
I have a class that is a core component of a performance sensitive code path, so I am trying to optimize it as much as possible. The class used to be:
class Widget
{
Widget(int n) : N(n) {}
.... member functions that use the constant value N ....
const int N; // just initialized, will never change
}
The arguments to the constructor are known at compile time, so I have changed this class to a template, so that N can be compiled into the functions:
template<int N>
class Widget
{
.... member functions that use N ....
}
I have another class with a method:
Widget & GetWidget(int index);
However, after templating Widget, each widget has a different type so I cannot define the function like this anymore. I considered different inheritance options, but I'm not sure that the performance gain from the template would outweigh the cost of inherited function invocations.
SO, my question is this:
I am pretty sure I want the best of both worlds (compile-time / run-time), and it may not be possible. But, is there a way to gain the performance of knowing N at compile time, but still being able to return Widgets as the same type?
Thanks!
The issue here is that if you store the widgets as the same type, then the code that retrieves the widgets from that store (by calling GetWidget) doesn't know N at compile time[*]. The code that calls the constructor knows N, but the code that uses the object has to cope with multiple possibilities.
Since the performance hit (if any) is likely to be in the code that uses the widgets, rather than the code that creates them, you can't avoid doing something in the critical code that depends on runtime information.
It may be that a virtual call to a function implemented in your class template, is faster than a non-virtual call to a function that uses N without knowing the value:
class Widget {
public:
virtual ~Widget() {}
virtual void function() = 0;
};
template <int N>
class WidgetImpl : public Widget {
public:
virtual void function() { use N; }
};
The optimizer can probably do its best job when N is known, since it can optimally unroll loops, transform arithmetic, and so on. But with the virtual call you're looking at one big disadvantage to start with, which is that none of the calls can be inlined (and I would guess a virtual call is less likely to be predicted than a non-virtual call when not inlined). The gain from inlining with unknown N could be more than the gain of knowing N, or it could be less. Try them both and see.
For a more far-fetched effort, if there are a reasonably small number of common cases you might even see an improvement by implementing your critical widget function as something like:
switch(n) {
case 1: /* do something using 1 */; break;
case 2: /* do the same thing using 2 */; break;
default: /* do the same thing using n */; break;
};
"do something" for all cases but the default could be a call to a function templated on the constant, then the default is the same code with a function parameter instead of a template parameter. Or it could all be calls to the same function (with a function parameter), but relying on the compiler to inline the call before optimization in the cases where the parameter is constant, for the same result as if it was templated.
Not massively maintainable, and it's usually a bad idea to second-guess the optimizer like this, but maybe you know what the common cases are, and the compiler doesn't.
[*] If the calling code does know the value of N at compile time, then you could replace GetWidget with a function template like this:
template <int N>
Widget<N> &getWidget(int index) {
return static_cast<Widget<N> &>(whatever you have already);
}
But I assume the caller doesn't know, because if it did then you probably wouldn't be asking...
You need to declare a non-templated type from which the templated type inherits, and then store the widgets as pointers to the non-templated base class. That is the only (type-safe) way to accomplish what you are looking for.
However, it is probably cleaner to keep the non-templated version. Have you profiled your code to see that the loops on the runtime-configured version are actually a bottleneck?
I guess the following is not an option?
template <int N>
Widget<N> & GetWidget();
Anyway, as soon as you’re managing several widget types together you cannot make them templated anymore since you can’t store objects of different type in one container.
The non-templated base class proposed by Michael is a solution but since it will incur virtual function call costs I’m guessing that making the class templated hasn’t got any benefits.
If your types are finite and known, you could use a boost::variant as an argument to your constructor.
The variant class template is a safe,
generic, stack-based discriminated
union container, offering a simple
solution for manipulating an object
from a heterogeneous set of types in a
uniform manner. Whereas standard
containers such as std::vector may be
thought of as "multi-value, single
type," variant is "multi-type, single
value."
here is some pseudo code
boost::variant< int, double, std::string > variant;
const variant foo( 1 );
const variant bar( 3.14 );
const variant baz( "hello world" );
const Widget foo_widget( foo );
const Widget bar_widget( bar );
const Widget baz_widget( baz );
Alternatively, you could use a boost::any for more flexibility.
You could write a templated GetWidget function. That would require you to know the type when you call GetWidget:
w = GetWidget<Box>(index);
I'm a little lost in how to cast templates. I have a function foo which takes a parameter of type ParamVector<double>*. I would like to pass in a ParamVector<float>*, and I can't figure out how to overload the casting operator for my ParamVector class, and Google isn't helping me that much. Does anyone have an example of how to do this? Thanks.
EDIT: Adding some code, sorry I'm an idiot and didn't phrase the original question well at all;
template<class T> class ParamVector
{
public:
vector <T> gnome;
vector <T> data_params;
}
template<class T> class ParamVectorConsumer
{
public:
ParamVector<T> test;
}
ParamVector<float> tester;
ParamVectorConsumer<double> cons;
cons.ParamVector = tester
will fail to compile. I would like to know how to write it so that I can cast the float version of tester to a ParamVector double. Thanks
EDIT2: Casting was the wrong word. I don't mind writing extra code, I just need to know how to get this to be accepted by the compiler so that I can write some sort of conversion code.
I'm not sure but maybe you need some like this:
template< typename TypeT >
struct ParamVector
{
template < typename NewTypeT >
operator ParamVector< NewTypeT >()
{
ParamVector< NewTypeT > result;
// do some converion things
return result;
}
template< typename NewTypeT >
ParamVector( const ParamVector< NewTypeT > &rhs )
{
// convert
}
template < typename NewTypeT >
ParamVector& operator=( const ParamVector< NewTypeT > &rhs )
{
// do some conversion thigns
return *this;
}
};
ParamVector< double > d1;
ParamVector< float > f1;
f1 = d1;
You can choose use conversion operator or operator= - I've provided both in my example.
Well, you can't. Each different actual template parameter, makes an entirely new class, which has no* relation inheritance relation with any any other class, with a diffent actual argument, made from that template.
No relationship. Well, except that each provides the same interface, so that inside a template you can handle then the same.
But neither the static types or the dynamic types have any relation.
Let me drop back here, and explain.
When I declare a pointer to classtype, like
Foo fp*;
fp has what we call a static type, of pointer-to Foo. If class Bar is a subclass of Foo, and I point fp at new Bar:
fp = new Bar1();
then we say that the object pointed to by fp has the dynamic type of Bar.
if Bar2 also publicly derives from Foo, I can do this:
fp = new Bar2();
and without ever even knowing what fp points to, I can call virtual methods declared in Foo, and have the compiler make sure that the method defined in he dynamic type pointed to is what's called.
For a template< typename T > struct Baz { void doSomething(); };
Baz<int> and Baz<float> are two entirely different class types, with no relationship.
The only "relationship" is that I can call doSomething() on both, but since the static types have no relationship, if I have a Baz<int> bi*, I can't point it to a Baz<float>. Not even with a cast. The compiler has no way to "translate" a call to the Baz doSotheing method into a call to a Baz::doSomething() method. That's because there is no "Baz method", there is no Baz, there are ony Baz<int>s and Baz<float>s, and Baz<whatevers>, but there's no common parent. Baz is not a class, Baz is a template, a set of instructions about how to make a class if and only if we have a T parameter that's bound to an actual type (or to a constant).
Now there is one way I can treat those Bazes alike: in a template, they present the same interface, and the compiler, if it knows what kind of Baz we're really dealing with, can make a static call to that method (or a static access of a member variable).
But a template is not code, a template is meta-code, the instructions of how to synthesize a class. A "call" in a template is not a call,it's an instruction of how to write the code to make a call.
So. That was long winded and confusing. Outside of a template definition, there is no relationship between a ParamVector and aParamVector. So your assignment can't work.
Well. Almost.
Actually, with partial application of templates, you can write a template function which gives a "recipe" of how to transform a Paramvector<T> to a ParamVector<U>. Notice the T and the U. If you can write code to turn any kind of ParamVector, regardless of actual template parameter into any other kind of ParamVector, you can package that up as a partially applied template, and the compiler will add that function to, for example, ParamVector.
That probably involves making a ParamVector<U>, and transforming each T in the ParamVector<T> into a U to put in the ParamVector<U>. Which still won't let you asign to a ParamConsumer<T>.
So maybe you want to have both templates and inheritance. In that case, you can same that all ParamVectors regardless of type inherit from some non-template class. And then there would be a relationship between ParamVectors, they'd all be sibling subclasses of that base class.
Notice that when you do an implicit cast, what the compiler can do without your help (I mean, without additional code) is just reference-upcast. That means that, seeing the object as a reference (for cast purposes only, the nature of the object doesn't change of course), it can look at it as one of its ancestors. When you have two template instances, none of them is an ancestor of the other (neither they are necessarily in the same hierarchy).
After trying that, the compiler looks for cast operators, constructors, etc. At this stage, probably a temporary object needs to be created, except when you're doing attribution and there's an attribution operator that fits.
One solution to your problem would be to use a conversion constructor:
template<class T> class ParamVector
{
public:
vector <T> gnome;
vector <T> data_params;
ParamVector()
{
}
template <class T2> ParamVector(const ParamVector<T2> &source)
{
gnome.reserve(source.gnome.size());
copy(source.gnome.begin(), source.gnome.end(), gnome.begin());
data_params.reserve(source.data_params.size());
copy(source.data_params.begin(), source.data_params.end(), data_params.begin());
}
};
This would create a temporary object whenever you use an instance of the template and other is required. Not a good solution if you're dealing with large containers, the overhead isn't acceptable. Also, if you pass a template instance to a function that requires not an object but a reference, the compiler won't call the conversion constructor automatically (you have to do an explicit call).
You are lost because you can't do it - the two types are completely different. Whenever you come across the need for a cast in your code, you should examine both your code and your design very closely - one or both is probably wrong.
You can't do this with a direct cast because double and float are completly different sizes. Doubles are going to be 64 bits while floats are 32. A pointer forced to cast from a
ParamVector<float>
to
ParamVector<double>
is going to misinterpret the data and give you garbage. You may want to google "pointer aliasing" or just learn more about pointers in general to see how this isn't going to work.
Think about it for a second you have one array that is a bunch of 64 bit values with fields layed out like this
0 => abcdabcd12341234
1 => abcdabcd12341234
If you force this to be interpreted as an array of 32 bit values, its going to not be interpreted correctly. You may or may not get something like
0 => abcdabcd
1 => 12341234
2 => abcdabcd
3 => abcdabcd
or it could be switched so that the 12341234's come first, or something stranger due to how the word ordering works out.
You mentioned "template casting" in your headline, so I'll presume that ParamVector is a templated type. That means that foo could be templated as well, and that would solve your problem.
template <typename T>
void foo(ParamVector<T> const& data)
{
}
You can't cast templates like this because the types are unrelated.
However, you can add a conversion function, such as:
(Your code wasn't really complete, so I can post complete code either. Hopefully you will get the idea.)
template<class T> class ParamVectorConsumer
{
public:
ParamVector<T> test;
template<T2> ParamVectorConsumer<T2> convert()
{
ParamVectorConsumer<T2> ret;
ret = this->...
}