understanding the definition of policy-based template - c++

template <
typename T,
template <class> class OwnershipPolicy = RefCounted, #1
class ConversionPolicy = DisallowConversion, #2
template <class> class CheckingPolicy = AssertCheck,
template <class> class StoragePolicy = DefaultSPStorage
>
class SmartPtr;
Q1> What is the syntax for the line #1
template <class> class OwnershipPolicy = RefCounted,
why it doesn't provide a parameter such as follows?
template <class T2> class OwnershipPolicy = RefCounted,
Q2> What is the difference between #1 and #2?
template <class> class OwnershipPolicy = RefCounted,
class ConversionPolicy = DisallowConversion,
Why one of these line have template<class> and the other doesn't?

template <class> class OwnershipPolicy is a template template argument. I.e. OwnershipPolicy is expected to be a template taking one (and only one) type argument. There's no name for that argument, because it's not needed, and you wouldn't be able to use it for anything anyway.
class ConversionPolicy is equivalent to typename ConversionPolicy, i.e. any ordinary type argument.
The difference lies in how you use it. For template template arguments, you provide only name of the template, which you can later use to instantiate concrete types. For typename, you need a concrete type:
template <typename A, template <typename> class B>
struct foo {};
template <typename T>
struct x {};
struct y {};
template <typename T, typename U>
struct z {};
// both of these are valid:
foo<x<int>, x> a;
foo<y, x> b;
// these are not:
foo<y, x<int>> c;
foo<y, y> d;
foo<y, z> e; // z has two template arguments, B must have only one
Worth noting that this idiom is called "policy-based design".

Related

what is this template doing?

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;
}

Simple concept check

Say I have a simple template like this:
template<typename T>
class A {};
And I want to specify that the type-parameter T is of some unrelated type X<U> where U is not known (or unspecifyable).
Is there a way how to express that as a concept?
Is there a way how to express that as a concept?
You don't need a concept, class template specialization works just fine in your case.
As an example, you can do this:
template<typename T>
class A;
template<typename U>
class A<X<U>> { /* ... */ };
This way, unless A is instantiated with a type of the form X<U> (where U is unknown), you'll get a compile-time error because the primary template isn't defined. In other terms, it won't work for all the types but X<U> (for each U), where the latter matches the class template specialization that has a proper definition.
Note that I assumed X is a known type. That's not clear from your question.
Anyway, if it's not and you want to accept types of the form X<U> for each X and each U, you can still do this:
template<typename T>
class A;
template<template<typename> class X, typename U>
class A<X<U>> { /* ... */ };
As a minimal, working example:
template<typename>
struct S {};
template<typename>
class A;
template<typename U>
class A<S<U>> {};
int main() {
A<S<int>> aSInt;
A<S<double>> aSDouble;
// A<char> aChar;
}
Both A<S<int>> and A<S<double>> are fine and the example compiles. If you toggle the comment, it won't compile anymore for A<char> isn't defined at all.
As a side note, if you don't want to use class template specialization and you want to simulate concepts (remember that they are not part of the standard yet and they won't be at least until 2020), you can do something like this:
#include<type_traits>
template<typename>
struct X {};
template<typename>
struct is_xu: std::false_type {};
template<typename U>
struct is_xu<X<U>>: std::true_type {};
template<typename T>
struct A {
static_assert(is_xu<T>::value, "!");
// ...
};
int main() {
A<X<int>> aXInt;
A<X<double>> aXDouble;
// A<char> aChar;
}
That is, given a generic type T, static assert its actual type by means of another structure (is_xu in the example) that verifies if T is of the form X<U> (for each U) or not.
My two cents: the class template specialization is easier to read and understand at a glance.
template <typename T, template <typename> class C>
concept bool Template = requires (T t) { {t} -> C<auto>; };
Now given a class template:
template <typename T>
struct X {};
a type template parameter can be constrained using:
template <typename T> requires Template<T, X>
class A {};
or:
template <Template<X> T>
class A {};
DEMO
This will work also for types derived from X<U>.

Template template partial specialization failure: "expected a class template"

This example code generates expected a class template, got std::pair <_T1, _T2>. I tried using struct Struct <std::pair> {};, but then parameters T and M become undeducible. How to avoid this?
template <template <class...> class>
struct Struct {};
template <class T, class M>
struct Struct <std::pair <T, M>> {};
Depending of what you want
template <template <class...> class>
struct Struct {};
template <>
struct Struct <std::pair>
{
// Specialization
};
or
template <typename> struct Struct {};
template <typename First, typename Second>
struct Struct <std::pair<First, Second>>
{
// Specialization
};
That is not a valid specialization for your template.
The reason why is because std::pair<T, M> is a full specialization of the class template std::pair and therefore a class. Your template expects a class template parameter which is exactly what the compiler is telling you.

How to specialize a class template with a template template parameter?

I'd like to specialize a class template on the type template parameter of the template template parameter. Is it possible? If yes, what is the syntax?
#include <type_traits>
template <typename T>
struct X {};
// primary template
template<template<class> class C>
struct Z : std::false_type {};
// specialization on the template template parameter
template<>
struct Z<X> : std::true_type {}; // OK
// specialization on the type template parameter of the
// template template parameter
template <template<class> class C>
struct Z<C<int>> {}; // ERROR
Motivation: Let's assume that the template template parameter denotes Collections (e.g. std::vector, std::deque). And I want to specialize Z on std::vector but I am not interested about the type template parameter of std::vector, that's OK. Also I want to specialize on all Collection types, which holds an int.
This question is similar to the following questions, but they are either trying to specialize a function template
How to specialize a template with template-tempate parameters
Specialize a template with a template
or they are trying to specialize not on the template template parameter
Specialization and template template parameters
or there's no template template parameter in the primary template
Templated class specialization where template argument is a template
The following code compiles fine:
#include <type_traits>
template <typename T>
struct X {};
// primary template, no template template parameter
template<typename T>
struct Z : std::false_type {};
// specialization on the template template parameter with arbitrary T
template<typename T>
struct Z<X<T>> : std::true_type {};
// here's where you need the template template parameter
template <template<class> class C>
struct Z<C<int>> : std::true_type {};
int main()
{
static_assert(!Z<Z<double>>::value, "" );
static_assert( Z<Z<int >>::value, "" );
static_assert( Z<X<double>>::value, "" );
// static_assert( Z<X<int >>::value, "" ); // error: ambiguous
// partial specialization
}
In your code you give Z a template template parameter, even though that should be done for the specialization only. That's why your code does not compile.
This cannot work because in your code:
template<template<class> class C>
struct Z : std::false_type {};
template<>
struct Z<X> : std::true_type {};
Z expects class template as a parameter.
template <template<class> class C>
struct Z<C<int>> {};
Here you are are not specializing any of it's template arguments and trying to pass C<int> which is not a class template (C is a class template and is different than C<int> which is concrete type).
If your class has template parameter which is a class template and you want your class to behave differently for different types passed for the container you probably should do something like:
template<template <typename> class Container,typename Element>
struct MyStruct
{
Container<Element> generic_elements;
// ...
};
template<template <typename> class Container>
struct MyStruct<Container,int>
{
Container<int> special_int_container;
void special_int_things();
//...
};

Deduce template parameter's template parameter

There is a class template A, which is taking template class for its template parameter.
template <typename T> class A {}
template <typename T> class B {}
int main()
{
A<B<int>>();
return 0;
}
Can class template A deduces its template parameter(B int)'s template parameter(int)?
Or is there the other way to solve this problem? For example,
template <typename T<typename U>> class A {}
You can make A a template template:
template <template <typename> class T, typename Inner>
class A<T<Inner>> {};
template<class>struct inner{};
template<template<class...>class Z, class T, class...Ts>
struct inner<Z<T, Ts...>>{
using type=T;
};
template<class Z>
using inner_t=typename inner<Z>::type;
and inner_t<X> is the first template argument of X if it exists, and a substitution failure otherwise.
What you described is a template template:
template< template<typename> class T > class A {};
note the class before T has to be class, not typename.