How to specialize a given template for a template - c++

Is it possible to specialize this template for any basic_string's?
template<class T> struct X {};
Since basic_string is a template itself, I know this would be a solution:
template <template <class, class, class> class T> struct X {}; template <> struct X<basic_string> {};
However, I would like to know if the language allows to preserve the first template definition, by specializing it somehow for basic_string's only.

Yes:
#include <string>
template <typename> struct X;
template <typename TChar, typename TTraits, typename TAlloc>
struct X<std::basic_string<TChar, TTraits, TAlloc>>
{
// ...
};
Your primary template takes one type parameter, so every specialization must supply one type parameter for X, one way or another.

Related

Template specialization for fundamental types

Is there any way to make a template specialization for fundamental types only?
I have tried to do the following:
template<typename T, typename = typename std::enable_if<!std::is_fundamental<T>::value>::type>
class foo
{
}
template<typename T, typename = typename std::enable_if<std::is_fundamental<T>::value>::type>
class foo
{
}
But I'm getting an error that the template is already defined.
Here you are creating two templated classes with the same name, not specializations.
You need to create a generic one and then specialize it:
// not specialized template (for non-fundamental types), Enabler will
// be used to specialize for fundamental types
template <class T, class Enabler = void>
class foo { };
// specialization for fundamental types
template <class T>
class foo<T, std::enable_if_t<std::is_fundamental<T>::value>> { };

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();
//...
};

Can you specialise using statements?

If I want some type to be specialised on its template parameter I generally use a struct:
template <bool value>
struct IsTrue;
template <>
struct IsTrue<true> : std::true_type {};
template <>
struct IsTrue<false> : std::false_type {};
An empty struct that gets its only functionality from inheritance isn't really that different from a using statement, so I was wondering, does something like template specialisation exist for using statements? Pseudocode of what I'm after below:
template <bool value>
using IsTrue;
template <>
using IsTrue<true> = std::true_type;
template <>
using IsTrue<false> = std::false_type;
Is something like this possible? What would it be called?
No, alias templates cannot be partially or explicitly specialized.
An earlier design did allow specialization, but the resulting semantics are rather...odd, at least viewed from today's angle. For example, in such a design, the following program would declare two different function templates:
template<class, class> class Meow {};
template<class T> using MeowInt = Meow<int, T>;
template<class> void f(Meow<int, T>);
template<class> void f(MeowInt<T>);
and this call would not compile because you wouldn't be able to deduce the template argument:
template<class T> using Purr = T;
template<class T> void f(Purr<T>);
f(42);

C++ template partial specialization

I cant figure out how to specialize partially this template. compiler complains that template parameter N is not used in partial specialization
#include <boost/multi_array.hpp>
template<typename T, class A>
struct adaptable;
template<typename T, size_t N>
struct adaptable<T,
// line below is the problem
typename boost::multi_array<T,N>::template array_view<2>::type>
{
typedef typename boost::multi_array<T,N>::template array_view<2>::type type;
};
I can add dummy template parameter just to silence compiler.
template<typename T, class A, class A0 = A>
struct adaptable;
template<typename T, size_t N>
struct adaptable<T,
typename boost::multi_array<T,N>::template array_view<2>::type,
boost::multi_array<T,N> >
{
typedef typename boost::multi_array<T,N>::template array_view<2>::type type;
};
is there more straightforward way?
I don't see anything in your example that looks like partial specialization. A partial specialization is a specialization that specifies exact types for some if the base template parameters, but leaves others open. For example:
template <class T, class U>
struct my_template {
// the base template where both T and U are generic
};
template <class T>
struct my_template<int> {
// A partial specialization where T is still generic, but U == int
};
To support partial specialization, the base template has to have at least two template parameters (call the number N). The partially specialized template can have 1..N-1 template parameters. The partial specialization must be located where the compiler will already have "seen" the base template before attempting to compile the partial specialization. The partial specialization is written as a completely separate template from the base template (though the base template and all specializations must have the same name, of course).