Template class specialization with template class - c++

Related questions:
c++ nested template specialization with template class
template class specialization with template class parameter
Consider the following code:
template <typename T>
struct is_std_vector: std::false_type { };
template<typename ValueType>
struct is_std_vector<std::vector<ValueType>>: std::true_type { };
Why is such template class specialization syntax correct?
The following seems more logical:
template <typename T>
struct is_std_vector: std::false_type { };
template<> //--- because it is is_std_vector specialization
template<typename ValueType>
struct is_std_vector<std::vector<ValueType>>: std::true_type { };

Class template partial specialization syntax closely mirrors function template syntax. Indeed, the rules for ordering class template partial specializations is based on function template partial ordering.
The way you would write a function taking a vector<T> is:
template <class T>
void is_std_vector(vector<T> ) { ... }
So the way you write a specialization on vector<T> is the same:
template <class T>
class is_std_vector<vector<T>> { ... };
Matching the specialization of is_std_vector would try to deduce T in vector<T> from some type argument A, so it makes a lot of sense that they're written the same way.
For full specializations, we use template <> as placeholder signal to make full specializations look similar to partial specializations. I'm not sure what purpose an extra template <> would serve in this particular case.

Related

How to do partial template class specialization with concept and requires?

It's easy to write template function override with concept, but I don't know how to write template class partial specialization :(
template <typename T>
concept Integral = is_integral_v<T>;
template <typename T>
concept IsNotIntegral = !
is_integral_v<T>;
template <typename T>
class Test
{
};
template <Integral T> // wrong
class Test
{
};
template <typename T> // wrong
requires Integral<T>
class Test
{
};
int main()
{
Test<int> t;
}
This doesn't work either:(
template <Integral T>
class Test
{
};
template <IsNotIntegral T>
class Test
{
};
Both
template <Integral T> // wrong
class Test
{
};
and
template <typename T> // wrong
requires Integral<T>
class Test
{
};
are using the declaration syntax of a primary class template, not a partial specialization. Compare the syntax of an unconstrained partial specialization from before concepts:
// primary class template
template <typename T>
class Test
{
};
// partial specialization of the class template
template <typename T>
class Test<T*>
{
};
The difference is that there isn't just a class name in the partial specialization after the class keyword, but a template-id Test<T*> instead. Without it a partial specialization makes no sense since we wouldn't know what template arguments we are specializing for.
So with constraints the syntax for a partial specialization should be the same:
template <Integral T>
class Test<T>
{
};
or
template <typename T>
requires Integral<T>
class Test<T>
{
};

C++20 Template Template Concept Syntax

With concepts, C++20 provides nice syntax like
template<typename T>
concept SomeConcept = true; // stuff here
template<typename T>
requires SomeConcept<T>
class Foo;
template<SomeConcept T>
class Foo;
where the two ways of concept restricting the class are equivalent, but the latter is just more concise.
If i now have some template template concept like
template<template<typename> typename T>
concept SomeOtherConcept = true; // stuff here
template<template<typename> typename T>
requires SomeOtherConcept<T>
class Foo;
i do not know the non-verbose (concise / short) syntax for this without an requirement clause, as things like
template<template<typename> SomeotherConcept T>
class Foo;
template<template<SomeOtherConcept> typename T>
class Foo;
did not work, so
What is the correct syntax for declaring such a template template class with a concept restriction to the template template parameter?
What is the correct syntax for declaring such a template template class with a concept restriction to the template template parameter?
The only way to write a constraint that depends on a template template parameter or a non-type template parameter is with a requires-clause. The shorter type-constraint syntax is only available for concepts that constrain types (hence the name type-constraint):
template <typename T> concept Type = true;
template <template <typename...> class Z> concept Template = true;
template <auto V> concept Value = true;
// requires-clause always works
template <typename T> requires Type<T> struct A { };
template <template <typename...> class Z> requires Template<Z> struct B { };
template <auto V> requires Value<V> struct C { };
// type-constraint only for type concepts
template <Type T> struct D { };
// abbreviated function template definitely only for type concepts
void e(Type auto x);
This is a trick that I have used before.
Define a lambda in the primary expression using a noop-like function as shown:
void noop(auto) {}
//...
template<typename T>
concept SomeConcept = true;
/*
template <template<typename>SomeConcept T>
struct Example {};
*/ //does not work
template <template<typename>typename T>
requires requires() {
{
noop(
[]<typename TArg> requires SomeConcept<typename T<TArg>> (){}
)
};
}
struct Example {};

specialize a template class for a template function

I have two template classes like
template <class T>
class MyClass1{};
template <class T>
class MyClass2{};
and I have a template function using them as an argument. The classes are specialized with std::string:
template <template class<std::string> T> myMethod(T<std::string>& arg){}
I'd like to use myMethod(objectOfMyClass1) and myMethod(objectOfMyClass2), but the code doesn't compile. How to specialize a template class for a template function?
First, if your method does not take any arguments, you won't be able to call it as you want.
Second, MyClass1 and MyClass2 are not classes but class templates -- you cannot therefore have objectOfMyClass1 and objectOfMyClass2.
If you your function to behave specially for an argument of any type of the form SomeClassTemplate<std::string>, then what you're after is partial function template specialization, which is not allowed in C++. You will have to use a partially-specialized class instead:
template <class T>
struct MyMethodCall;
template <template <typename> class T>
struct MyMethodCall<T<std::string> > {
static void call(T<std::string> object) {
...
}
};
template <class T>
void myMethod(T & object) {
MyMethodCall<T>::call(object);
}
This is a compilable example
template <class T>
class MyClass1{};
template <class T>
class MyClass2{};
template <template <typename> class T>
void myMethod(T<std::string>& arg){}
int main()
{
MyClass1<std::string> c1;
myMethod(c1);
MyClass1<std::string> c2;
myMethod(c2);
}

Why can't I specialize the nested template member without specializing enclosing class template first?

Here is the code :
template <typename T>
struct A
{
template <typename U>
struct B;
};
template <typename T> template <> // 0_o
struct A<T>::B<int> {};
I know I can't do this but I'm more interested to know logically Why can't I specialize the nested template member without specializing enclosing class template first?
I appreciate any help with logical explanation :)
Edit :
Andrei Alexandrescu's reply : "There's no particular reason - it's just a language rule."
Here's an idea based on Xeo's example: First, let's have our candidate primary template:
template <typename T> struct Foo
{
template <typename U> struct Bar { /* ... */ };
/* ... */
};
Now suppose we want to specialize the inner template, hypothetically:
template <typename T> template <> struct Foo<T>::Bar<bool> { /* ... */ }
// not actual C++!
But now suppose there are specializations of Foo:
template <> struct Foo<int>
{
template <typename U> struct Bar { /* ... */ };
};
template <> struct Foo<char>
{
template <typename U> U Bar() { }
};
Now what if you want to use Foo<S>::Bar<bool>? When S = char, we cannot use the inner specialization, because it makes no sense. But if we disallow the inner specialization for all specializations of the outer template, then Foo<int>::Bar<bool> isn't specialized, while Foo<float>::Bar<bool> will be specialized. So our hypothetical inner specialization does not apply to Foo<int>, even though one might have expected that it should.
This isn't a real technical reason that it can't be done, but just an illustration how it would have very unexpected behaviour. (For instance, imagine the specialization for int was written later, and existing code depended on the inner specialization.)

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).