Is it possible to specifiy a template as a member but not know all the details? Or rather how can I work around this.
Example doesn't work but might show you what I'm trying to achieve.
template<typename T>
struct Foo {
///blah...
};
struct Bar {
Foo* m_foo;
};
Bar in this case is a base class, and depending on the derived classes I wont know the full details of Foo
You can either make Bar a template class as well so it can pass that template argument along to Foo, or else you can make all the Foo<T> variations inherit from a common interface (in C++, an interface is just an abstract class with no implementation, all members are pure virtual functions) and then Bar can point to that interface.
The first way is better if Bar is just going to provide some functionality which will be reused by a bunch of derived classes.
The second way is better if descendants of Bar are going to be used polymorphically.
The code you have above won't work, since whenever you use a C++ template you must specify what it's arguments are. If you want to store a Foo of an unknown type, you can do so by parameterizing Bar over some type (for example, making it a template with type argument T), then having Bar store a Foo. This contrasts with other languages like Java where code like what you have outlined above is legal because templates work differently in C++. In particular, Java-style genetics just compile down to one concrete representation, then use runtime checks to verify that they're being used properly. C++ template instantiations all end up getting compiled down into separate code, and so the compiler has to be able to infer at compile-time what the argument types are (so it knows what code to generate).
Related
I am using a C++ class which is templated.
I instantiate two different templated version of this class:
ExampleClass<ParamType1> obj1;
ExampleClass<ParamType2> obj2;
So that I have two objects which are the same class, but with different template parameters.
I now want to be able to define a function (extremely simplified example!) that can take either obj1 or obj2 as a parameter:
int func(ExampleClassXXX obj_param)
{
return obj_param.member_operation();
}
So that I can call either func(obj1) or func(obj2.
Is this something that is possible, and if so, what is the syntax needed for the function definition to specify the obj_param parameter is "an instance of ExampleClass created with any template parameters"?
The answer to this question sort of covers the case that is one step more general - having "obj_param" be any type. Most of the details are missing from the text of that answer, it is only when you click on the "live demo" that you see they are instantiating a templated struct to be able to pass in the generic parameter, which is pretty ugly.
It seems like this should be a common thing to want to do, but Googling has failed me so far (searching for "passing templated object as function parameter")
Note that
ExampleClass<ParamType1>
and
ExampleClass<ParamType2>
are basically two different classes for the language.
You have two possibilities, in my opinion, the first being:
template<typename ParamType>
int func(ExampleClass<ParamType> obj_param){}
The second possibility is to give to ExampleClass a non-templated public base class (basically implementing type erasure) like so
template<typename T>
class ExampleClass : public ExampleClassBase{};
and then re-write the function as
int func(ExampleClassBase& obj_param){}
but you will not be able to pass by value in this case because of object slicing issues.
The template function forces you to implement the function in a header file if you want to keep it as general as possible, the non-templated base class forces you to pay for virtual function call.
Edit: as per Alan Birtles comment, if you know already all the types you will instantiate ExampleClass with you can implement each version of the function in a cpp file.
So that I have two objects which are the same class, but with different template parameters.
A contradiction right there. If the arguments are different, this is not the same class. A template is not a class, it's a mold. If you pour two different metals into it, you'd get two very different objects, despite the similar shape. They'd have different mass and density, possibly different electromagnetic properties, and so forth. A bit tangential, but it's important to differentiate the template from the things it produces, those are not the same.
This is why different specializations produced from the same template are considered different classes. They are not related under the type system, and so no function can automatically treat them as the same thing. You could create a function template, and use it to generate functions for each distinct specialization, but those too would be different functions.
If you have a part that's common to all specializations, you could refactor it out into a base class (proper class, not a class template), and have a function that accepts that.
I have a large class which basically handles one buffer of variable (numeric) datatype. So it seems a good choice to use a class template with this datatype as the only parameter. I'm not experienced in C++ and I wonder/worry a bit about the "footprint" such a template makes in my code.
There are three implications of templates which in my (C++ unexperienced) eyes are not necessary and make code ugly. I tried to avoid them, but neither did I find a good example how to do it nor did I manage to find it out by myself.
So the goal of this question is: Can you either confirm the following statements or give a counterexample?
When using a class template, all class methods have to go into the header file. Even if they have no templated type in their interface or implementation.
When using a static method or member of the class, I always have to specify a template parameter (MyClass< double > :: MY_STATIC), even if the templatization does not affect any of the static properties of the class.
When using the class as a parameter for a function, I always have to give a template parameter, even when this function does not access any of the templated members? (function myFunc(MyClass< double> & myClass){ do something } )
As a general rule, don't have functions/data members in a template class which does not use the template parameters. Have a base class, put all non-template related things there, your template class should derive from it.
To answer your questions:
yes, everywhere where you need to instantiate the template, you need to see the full definition of the class and it's functions
yep, but put that into the base class
yes, see above
EDIT: One of the reasons to move to base class is code bloating (this expression actually exist, you can google it for more info): If you don't move the template unrelated code to a base class, the very same template independent code will be copied for all instantiation of your template, which means a lot of unnecessary code. If you put it to a base class, you will only have this code once.
Yes. On the plus side, the code is only generated when the metod is actually used for the specialization.
Yes. However, there is no (other then design choice) need for a static method to be a memeber of the templated class if it has no use for the templated parameter.
Yes. The size and memory layout of the structure is determined by the template parameter.
In accessing a using from a base class with a templated base class, I've run into an issue with verbosity if nothing else. In the below code, the derived class attempts to use the my_type from its base class.
template <typename T>
class Base {
public:
using mytype = T;
};
template <typename T>
class Derived : public Base<T>{
public:
// using the base's mytype here
static typename Base<T>::mytype func() { return 0;}
};
However, in practice I'm finding this to be an awful lot of characters for what seems like it should be simpler. if the Base class was not templated then it wouldn't require the <T> or the typename (obviously).
In my real issue, I have a great deal of classes deriving from the base and I want to simplify this if possible. What I have at the moment is like the next example, where I'm just adding an additional using to get the type from the base class, but it feels like an extra layer that I shouldn't need to have.
template <typename T>
class Derived : public Base<T>{
public:
using base_type = typename Base<T>::mytype;
static base_type func() { return 0;}
};
this may seem like a silly issue, but the number of times the base class's mytype is used in the derived classes makes it pretty hideous in the former case. Is there a right way to get the types out of the templated base that maintains readability?
This is a well known quirk of the language for which there is no real solution. Lookup in templates is done in two separate steps, during the first phase of lookup before instantiation non-dependent names are resolved to their meanings, while in the second phase dependent names are resolved after instantiation.
The division of the two phases was included in the language to provide some sanity for the template developer that does not know where the template will be instantiated. The first phase of lookup is done at the point where the template is defined, and it can be reasoned about by the developer at exactly that point. At one point or another, the template will do operations that depend on the arguments, and those cannot be resolved where the template is defined, since the template arguments are not yet fixed. Those names are considered dependent, and lookup is postponed to the second phase, after substitution of the template arguments, so that ADL can kick in.
How does this relate to your particular problem? When you inherit from a non-template base, the developer has fixed what the base is, and that can be looked up at the point of the template definition as you expect. But when the base depends on a template argument, the definition of the base class is not known at the place of the derived template definition. In particular, without substituting the type in, the compiler cannot possibly know whether there is a specialization for this particular type. This implies that during the first phase the compiler cannot assume anything at all about the base and thus lookup cannot search into it.
The direct way of using a typedef in a base is for the developer of the derived template to explicitly tell the compiler that it wants a type and that the type will be defined in the instantiation of the base template. The key point here is that the compiler knows nothing about the base, but the developer can require that uses of this template comply with a contract in which the instantiation of the base must have that nested type. The developer is free to add constraints on the types of her template, the compiler is not.
The syntax for that is the one in your first block: typename Base<T>::type to refer to the type, which tells the compiler that the contract of use requires that whatever T is used to instantiate Derived, the user is required to ensure that Base<T> will contain a nested member type that is a type (typename). As a short hand, you can opt for the second approach: create a local typedef that will be found inside Derived and resolved to that. In that case, regular lookup during the first phase will find the nested typedef, determine that it refers to a dependent name and postpone the complete lookup for the second phase.
While this is not an answer to the question of whether there is a better way (readability wise), I hope it provides some understanding as of why things are like they are. The decision while designing the language was not arbitrary [it might or not be ideal, some people believe the first phase is unneeded and unwanted, but it was not arbitrary]
Maybe I'm missing something obvious here, but you can simply use using on the type directly without having to give it a new name:
template <typename T>
class Derived : public Base<T>{
public:
using typename Base<T>::mytype;
static mytype func() { return 0;}
};
You can even decide if the using-declaration for mytype should go into the public, protected or private section.
template <class T> void checkObject(T genericObject)
{
MyClassA* a = dynamic_cast<MyClassA*>(genericObject);
if (a != NULL)
{
//we know it is of type MyClassA
}
MyClassB* b = dynamic_cast<MyClassB*>(genericObject);
if (b != NULL)
{
//we know it is of type MyClassB
}
}
Is something like this possible? where we have a template type but we want to know it's actual type?
In the world of templates you probably want to just specialize templates for each of your types instead of doing a runtime check, ie
template<typename T>
void foo(T obj);
template<>
void foo<MyClassA>(MyClassA obj) {
}
template<>
void foo<MyClassB>(MyClassB obj2) {
}
This will allow the compiler to generate the correct template at compile time by deducing on your args.
Note this only resolves based on a instance's static type, that is there's no compile-time knowledge that your variable is a MyClassC which inherits from MyClassB and therefore should use the generic form. So this won't work:
MyClassC* cinstance = new MyClassC();
foo(cinstance); //compiler error, no specialization for MyClassC
In general this points to a general rule that compile-time and run-time polymorphism are very different systems. Templates deal strictly in the realm of static types without knowledge of inheritance. This may surprise folks coming from Java/C# which have a more seamless integration between the two features.
For run-time specialization of functionality for a class, your options are
Define virtual methods -- may not be appropriate depending if this bit of functionality truly should be a part of this object
Use dynamic_cast (what you're currently doing) -- somewhat frowned upon, but can be the most straight-forward solution that everyone gets.
Visitor Pattern -- a design pattern that uses overloading to resolve to a function of the correct type at run-time.
It is possible but MyClassA and MyClassB must have at least one virtual member function in order for dynamic_cast to work. I also believe you actually want to have (T* genericObject) rather than T genericObject in your function's signature (it would make little sense otherwise).
Solutions based on template specializations are OK for static polymorphism, but I believe the question is how to enable run-time detection of the input's type. I imagine that template being called with a pointer which is of a type that is either a superclass of MyClassA or a superclass of MyClassB. Template specialization would fail to provide the right answer in this case.
Anyway, I have a strong feeling that you are trying to do the wrong thing to achieve what you want to achieve (whatever it is). When you post this kind of questions, I suggest you to make clear where you want to go, what is your goal; this one might just be an obstacle along the wrong path.
Yes this is possible. Please note that dynamic cast happens during runtime and templates generate code durign compilation. Thus the function will still be generated but will do checks during runtime for the cases you describe.
EDIT: have a look at Doug T.'s answer for the right way to do what you try to do.
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.