I have a template class defined :
template <class T>
class TempClass
{
...
};
If I want to make an object of this class in let's say some MyClass.h to access functions of template class, how shall I pass the argument of the template?
I tried to do the following:
class MyClass{
public:
TempClass<T> temp;
}
Sure, as supposed it does not work, as T is not defined in MyClass, so I am a bit lost how do it correctly.
Thanks.
If you want MyClass to be a template as well, you would do it like this:
template<typename T>
struct MyClass {
TempClass<T> temp;
};
(You could also use class instead of struct, but since all members are public, you don't really need default private.)
If you don't want MyClass to be a template, you will need some concrete type to substitute in for T. For example:
struct MyClass {
TempClass<string> temp;
};
Pedantic: Technically TempClass isn't a template class, it's a class template. A class template isn't actually a class, it's a template that can be used to create individual classes that are themselves template classes. Thus, TempClass is a class template, while TempClass<string> is a template class --- a class that is created by instantiating a template.
Templates are not classes. Are. as it name means, templates wich helps the compiler to create classes. That is, if you have a template class template<typename T> class Foo{};:
template<typename T>
struct Foo
{
T attribute;
};
Its only a template which the compiler uses to generate different versions of Foo, each for a specified type. When you instantiate a template, that is, tells the compiler you need that class generated with a specified type, the compiler generates a version of Foo code replacing the template argument with the specified type:
int main()
{
Foo<int> foo_int_variable;
Foo<bool> foo_bool_variable;
}
The compiler after seeing that two instances, generates code like this:
struct __Foo_int
{
int attribute;
};
struct __Foo_bool
{
bool attribute;
};
So the code of main is translated to this:
int main()
{
__Foo_int foo_int_variable;
__Foo_bool foo_bool_variable;
}
So the answer is: You need to specify what type you need, to let the compiler to generate the correct template instantiation.
If the class that uses Foo, like in your example, don't need a specific instantiation of Foo, needs a generic version of Foo, you could make that class a template too.
You can instantiate your template like this, for example, to instantiate for int:
class MyClass
{
public:
TempClass<int> temp;
};
But if you still want you MYClass to be generic, you can make it template too and define it like this:
template<typename T>
class MyClass
{
public:
TempClass<T> temp;
};
and let the any MyClass object instantiation to define parameter T, for example:
MyClass<int> class;
Related
I have some code like this
class A : public b<T>
{
public:
typedef b<T> _baseclass; // why we need this declaration
};
What is the use of typedef inside the class?
Is the definition limited to this class only?
Shall we create this as static and use without crating an object of the class?
This member type will be available outside of the class definition too, which is convenient in template code. If you passed an A into a function template, or maybe some other classes that also have _baseclass member types, then you can use _baseclass to find out what the base is without needing to know exactly what the top-level type is.
Standard templates like std::vector and std::map have member types like value_type — these do not signify a base class but have a similar purpose, in that you can use value_type anywhere a container is used, no matter which container is used.
Swapping typedef to using (because I want to), here's an example:
// The class templates
template <typename T>
struct Base {};
struct A : Base<int>
{
using base_class = Base<int>;
};
struct B : Base<char>
{
using base_class = Base<char>;
};
struct C : Base<bool>
{
using base_class = Base<bool>;
};
// The example
template <typename T>
void foo()
{
// typename needed because base_class is a "dependent name"
// (just go with it)
typename T::base_class the_base;
// This line is to suppress "unused variable" warnings
(void)the_base;
}
int main()
{
foo<A>();
foo<B>();
foo<C>();
}
Though this particular program doesn't actually "do anything", it shows a function template foo that can "know" what the base class was in each case, without any further information about exactly what T is. And it'll work for any class to which you've added a base_class member type!
EDIT: I didn't actually get a chance to test out any of the suggested solutions as I went on a vacation, and by the time I was back, the people responsible for the class template had made some changes that allowed me to get around the need to use types defined in the class template itself.
Thanks to everyone for their help though.
In a nutshell - and feel free to correct my wording, templates are still a bit of voodoo to me, - I need to know if I can use a (protected) struct or a #typedef defined inside a class template from my specialized class. For example:
This is the class template:
template<typename T>
class A : public C<T>
{
protected:
struct a_struct { /* Class template implementation, doesn't depend on T */ };
void foo( a_struct a );
};
Which I need to fully specialize for T = VAL:
template<>
class A< VAL > : public C< VAL >
{
void foo( a_struct a )
{
// My implementation of foo, different from the class template's
}
};
If I do something like this, however, the compiler complains that a_struct is undefined in my specialized class. I tried specializing and inheriting from the class template but that got... messy.
I saw some solutions, but all of them involved modifying the class template, which is something I am not able to easily do (different team).
Thoughts?
No, you can't use members of the primary template declaration in your specialization of the class template. That is because in essence a template class specialization declares a completely new class template that is applied when the template arguments match the specialization.
You have two options available though, if you want to do something like in your example:
You can specialize the template class member function. This is useful if it is indeed only one member function that is special (or at least the number of member functions is limited).
You can bring the declaration of the member (-type) in a common base class.
Since you indicated in an edit that you can't change the class template itself, specializing the member function seems the best option.
A simplified example of specializing a member function only
template< class T>
class Printer
{
public:
struct Guard {};
void DoPrint( const T& val)
{
Guard g;
(void)g;
std::cout << val << '\n';
}
};
struct Duck {};
template<>
void Printer<Duck>::DoPrint( const Duck& val)
{
Guard g;
(void)g;
std::cout << "Some duck\n";
}
The Guard here is only used to demonstrate that this type is available to both the primary and the specialized implementation of DoPrint().
It's not beautiful, but you can do it like this:
template<typename T>
class C
{
};
template<typename T>
class A : public C<T>
{
protected:
friend A<int>;
// ^^^^^^
struct a_struct { /* Class template implementation, doesn't depend on T */ };
void foo( a_struct a );
};
template<>
class A< int > : public C< int >
{
using a_struct = typename A<void>::a_struct;
// ^^^^^^
void foo( a_struct a )
{
// My implementation of foo, different from the class template's
}
};
or how about, re-declaring struct a_struct in the specialized template, with same functionality as default one.
I know it may not sound good since you need to inject in all specialized templates. But that is one i can think of now.
In order to use a library, I need to use different classes that have the same base name. I.e.
MyClass
MyClassImpl
PreMyClass
And so on. in order to use them with template I need pass all these class names.
template <typename T, typename TImpl, typename PreT>
class ClassThatUsesAllTheseObjects
{
public:
ClassThatUsesAllTheseObjects();
private:
T myClass;
TImpl myClassImpl;
PreT myPreClass;
};
It's possibile to obtain the same result giving only the principal MyClass as template argument, building other names when needed?
Am not sure of the settings in your question, but in some cases, you might want to do something like the trait mechanism.
Suppose you write a concrete MyClass, and others like it. For each group of concrete classes, you do something like:
// This is common
template <typename T>
struct foo_traits
{
};
// This is for each set of concrete classes
template<>
struct foo_traits<MyClass>
{
using Impl = MyClassImpl;
using Pre = PreMyClass;
};
...
Then you use the traits class like this:
template <
typename T,
class Impl = typename foo_traits<T>::Impl,
class Pre = typename foo_traits<T>::Pre>
class ClassThatUsesAllTheseObjects
{
public:
ClassThatUsesAllTheseObjects();
private:
T myClass;
Impl myClassImpl;
Pre myPreClass;
};
This allows you to explain what are the "natural friends" of your principal concrete classes.
I can think of two options:
Use a tag to make the difference. So you would have e.g. a template <class T> myClass, a struct impl_t{}, struct pre_t{}, struct base_t{} and then use gthem in this way:
code:
myClass<base_t> ; // instead of plain MyClass
myClass<impl_t> ;// instead of plain MyClassImpl
myClass<pre_t> ; // instead of myPreClass
Template specialization should make their definition easy/possible.
traits, but there is already an answer on that side :-)
I am thinking about using curiously recurring template pattern for my application. However, I would like the classes to operate on the user defined types. I would like to understand if it is possible to create a structure similar to the one shown below:
template <class T_leaftype>
class BaseTrajectoryPoint {
};
template <class MyType>
class MyTrajectoryPoint: public BaseTrajectoryPoint<MyTrajectoryPoint> {
private:
MyType A;
};
The code above fails to compile with the following error:
type/value mismatch at argument 1 in template parameter list for ‘template class BaseTrajectoryPoint’
Are there any alternative ways of approaching the problem? I would like to use static polymorphism, but I would prefer to define all possible methods in the base class.
template <class T_leaftype>
class BaseTrajectoryPoint {
};
template <class MyType>
class MyTrajectoryPoint: public BaseTrajectoryPoint<MyTrajectoryPoint<MyType> > {
private:
MyType A;
};
MyTrajectoryPoint isn't a type, it's template; when you pass it as template parameter, it's seen as template<typename> class T>, not template<class T> - and the latter is what your base class is expecting. But MyTrajectoryPoint<MyType> names a type, so you can use it as template parameter of your base class.
Of course, you can change declaration of BaseTrajectoryPoint to template<template<class> class T_leaftype>, but then you would have to use class template as template parameter, never a complete type.
What our friend Griwes said is correct, although if you know that every class that will inherit BaseTrajectoryPoint is a template class, you can do the following:
template<template < class > class TLeaf> // << This means: It is expected a template class as parameter
class BaseTrajectoryPoint{
};
template <class MyType>
class MyTrajectoryPoint: public BaseTrajectoryPoint<MyTrajectoryPoint> >{
private:
MyType A;
};
Is it possible to write template definition for this data type?
myclass<int, myclass<int> > data;
Second template variable should be optional with default value of the same type.
Clarification
Now I use this definition:
class defaultClass { };
template <typename T, typename C=defaultClass>
class myclass { ... };
I'd like to predefine that defaultClass is myclass<T>
I'd like to implement something like auto implemented properties: the second parameter should be context in which the wrapped variable is defined. If the context is ommited, it should be in the object created by the template class itself. (I realize it could be solved another way, this is just use case.)
Looks very similar to
http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
You can do the thing you want by making a class hierarchy with template base type and then each of your classes may be derived from that base like
template<class T> class base { ... };
class derived: public base<derived> {...};