I can't for the life of me get this to work.
I have an existing template:
template <class T>
class MyTemplate;
Now I want to specialize it, but for a class T that's a template--without further specializing the second template, for example:
template <>
template <class T>
class MyTemplate<vector> { /*...*/ };
But this, and various other syntaxes I've tried don't seem to compile. What's the syntax for this? Or is it even possible? If not, are there possible alternatives for MyTemplate so that I could handle, say, a generalized specialization for both vector and map?
I think you're looking for this:
template<typename T>
class MyTemplate {...}
template<typename T>
class MyTemplate<vector<T> > {...}
Above, the partial specialization is used when you make a MyTemplate<vector<int> > x; and T is int.
The proper syntax is :
template < typename T>
class MyTemplate<vector<T> > { /*...*/ };
more generally
template<typename A, typename B> class MyTemplate;
template<typename C, typename D> class SomeTemplate;
template<typename A, typename C>
class MyTemplate<A, SomeTemplate<C,A> > { /* ... */ };
A template can be defined either in terms of:
non-type parameters (constants)
type parameters
template parameters
once it has been so defined, any specialization must respect the kind of the parameter.
Therefore, if you want to specialize for a vector (which is a template) where a type parameter is expected, you need to spell out the parameters of the vector to create a (templated) type parameter:
template <typename T, typename Alloc>
class MyTemplate < std::vector<T, Alloc> > {
};
Similarly for map, though there are more parameters:
template <typename K, typename V, typename C, typename A>
class MyTemplate < std::map<K, V, C, A> > {
};
and here you go :)
I'm not sure about the syntax for defining a template for a class. You need to look that up. However defining the template is not the catch all. You need to write the class definition for each template. For example if you have an class define to do talking 1 argument of type x, and taking 2 arguments of type y, or etc... then you need a class to handle it. Same as function overloading . You have the same function name but each takes different arguments. You write a function for each. And that call picks the right function based on the argument list.
So a class that ... will sort different objects by defining for each type.
Related
from https://github.com/wjakob/tbb/blob/master/include/tbb/tbb_allocator.h#L150
template <typename T, template<typename X> class Allocator = tbb_allocator>
class zero_allocator : public Allocator<T>
{...}
what I understand is that this is a definition for a new class, that inherits from the Allocator type visible in that translation unit .
the part that I don't get is template<typename X> class Allocator = tbb_allocator .
according to the tbb docs the zero_allocator takes 2 inputs, the type T and how many objects of type T you need to allocate . the zero_allocator also inheriths from the tbb_allocator which in turns defaults to a "standard" malloc/free behaviour if TBB is not present when linking .
I still don't think I get that syntax, especially the template<typename X> class Allocator part .
Can you explain this syntax and what is achieving ?
template <typename T, template<typename X> class Allocator = tbb_allocator>
class zero_allocator : public Allocator<T>
{...}
What we have:
template starts declaration of a template
it is followed by the template parameter list:
<typename T, template<typename X> class Allocator = tbb_allocator>
The first template parameter is "some type" T
the next one is not a type, it is a template itself.
template<typename X> class Allocator
So the template class zero_allocator needs to get instantiated with first
parameter is any type T and with second parameter a template which itself takes on template parameter X must be given.
In addition, the second template parameter for zero_allocator can be left, in this case for Allocator parameter the template tbb_allocator is used.
Here a full compileable example:
template <typename Y>
class ExampleTemplate {};
// and the one which is used as the default
template <typename Y>
class tbb_allocator {};
template <typename T, template<typename X> class Allocator = tbb_allocator>
class zero_allocator : public Allocator<T>
{
// Lets use the type T:
T some_var; // in our example, this will be "int some_var"
// and here we use the Template Template thing...
Allocator<float> some_allocator;
};
int main()
{
zero_allocator< int, ExampleTemplate > za;
}
I am trying to understand type function in template metaprogramming trough some examples.
I have created one example that removes the reference from a type.
template <class T>
struct remove_reference
{ using type = T; };
template <class T>
struct remove_reference<T&>
{ using type = T; };
int main(){
typename remove_reference<int&>::type a;
}
My question is if this is implemented using partial template specialization of if we call it something else?
I feel it is partial because we have not defined it for a specific type but I also feel it isn't because we have just as many template arguments.
The naming may not be important to understanding type functions but I don't want to teach other people the wrong names if I explain it.
Yes, it is partial specialisation, because you have restricted to just things that match the pattern T&.
You don't need to have fewer template parameters, you can even have more. E.g.
template <typename Callable>
struct function_something { ... }; // Any functor type
template <typename Ret, typename Args...>
struct function_something<Ret(Args...)> { ... }; // Specialises free functions
template <typename Class, typename Ret, typename Args...>
struct function_something<Ret(Class::*)(Args...)> { ... }; // Specialises member functions
Alright, I'm struggling with templates. In this question I learned, that it is not possible to pass a type specifier to a function at all, so my next approach is passing the type inside <>.
Imagine a function template foo<U>(), which is member function of a template class A. So if I create an Object A<T> a I can call a.foo<U>() with any type.
How do I have to write an equivalent function template so I can pass a and U like wrappedFoo<U>(a)?
IMPORTANT Needs to be C++98 compliant
You might do the following:
template <typename U, typename T>
XXXX /* See below */
WrappedFoo(/*const*/ A<T>& a)
{
return a.template foo<U>();
}
The hard part is the return type without decltype of C++11.
So if the return type really depends of parameters type, you can create a trait, something like:
template <typename U, typename T>
struct Ret
{
typedef U type;
};
template <typename T> struct Ret<T, A<T> >
struct Ret
{
typedef bool type;
};
And then replace XXXX by typename Ret<U, T>::type
How can I specialize a class template so that the template parameters can be of type : a pointer to a particular class or a pointer to the derived class of that particular type? Is it possible to do it without using Boost?
Possible Duplicate of: C++ templates that accept only certain types
I just wanted to know whether the answer is same even if I am using a pointer to the instances .
You could specialize your class for pointers and then use std::is_base_of with a static_assert:
template <typename T>
class foo;
template <typename T>
class foo<T*>
{
static_assert(std::is_base_of<Base, T>::value, "Type is not a pointer to type derived from Base");
};
See it in action. Both std::is_base_of and static_assert are C++11 features so no Boost is required.
If for some reason you don't like static_assert, you could do it the enable_if way:
template <typename T, typename Enable = void>
class foo;
template <typename T>
class foo<T*, typename std::enable_if<is_base_of<Base, T>::value>::type>
{
// ...
};
A technique for having specializations based on some predicate instead of a pattern is to use an extra defaulted parameter.
template <typename T, bool = predicate<T>::value>
class foo {
// here is the primary template
};
template <typename T>
class foo<T, true> {
// here is the specialization for when the predicate is true
};
All you need is a proper predicate. In this case, std::is_base_of seems to fit. There is a boost implementation of it too.
I have another C++ template question. I am a lazy guy, so I try to not specify template arguments if possible. Now I have a function
template< typename EasyLookingObject >
void myfunct( EasyLookingObject& obj ) {
//do something with obj
}
Now, EasyLookingObject is in fact a
boost::ptr_list< A< STDContainer::<TargetType*> > >
In order to work with obj, I need to know the types of STDContainer and TargetType. Can you help me to get these types?
Problem 1: EasyLookingObject::value_type does give me a pointer type. How do I deduce the full type from it and use it within a typedef?
The same probably applies to the STDContainer::value_type issue.
Removing the pointer is trivial using partial specialisation:
template <typename T>
struct remove_ptr {
typedef T type;
};
template <typename T>
struct remove_ptr<T*> : remove_ptr<T> { };
(I’m sure Boost also has something like this.)
Putting it all together:
typedef typename remove_ptr<typename EasyLookingObject::value_type>::type a_t;
typedef typename a_t::container_type container_t;
typedef typename remove_ptr<typename container_t::value_type>::type target_t;
Problem 1: EasyLookingObject::value_type does give me a pointer type. How do I deduce the full type from it and use it within a typedef?
You probably don't need to extract the typedefs.
Just pass every extracted item to another overloaded function. Use an extractor function akin to boost::get_pointer() to extract a pointer from a reference, or a plain or smart pointer.
template<class Container>
void do_something_item(Item* item); // overload for different types as necessary
template<class Container>
void do_something(Container& c) {
for(typename Container::iterator i(c.begin()), j(c.end()); i != j; ++i) {
using boost::get_pointer;
do_something_item(get_pointer(*i)); // use ADL to find get_pointer() overload
}
}
If you really can't infer the correct types from class typedefs (which I doubt, double check the documentation), the you can specify the template parameters a bit more explicitly:
template <template <typename...> class Container, typename T, typename ...Args>
void myfunc(const Container<T*, Args...> & c)
{
// ...
}
If you don't have variadic templates, you'll have to specify as many arguments as your container takes, or specify default arguments if you only want the template to match those. Here's a defaulting version that works for two-parameter containers:
template <template <typename A, typename = std::allocator<A> > class Container,
typename T>
void myfunc(const Container<T*> & c);
This will only match Container<T*, std::allocator<T*>>. Here's a general version for two-parameter containers:
template <template <typename , typename> class Container,
typename T1, typename T2>
void myfunc(const Container<T1*, T2> & c);
Concretely, your function should be a variation of this:
template <template <typename> class Container, typename T>
void myfunc(const boost::ptr_list<A<Container::<T*> > > &);