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

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

Related

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

Template class specialization with template class

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.

How to define a function for a (somewhat) partially specialized class

I'm not sure if what I'm trying to do is possible. Here's an example:
template <typename T>
class Ref
{
void Decrement();
};
template <typename T>
class Collection {};
// This will error
template <>
template <typename T>
void Ref<Collection<T>>::Decrement() {}
You can't specialize just one function inside a class template; you have to specialize the class template as a whole.
template <typename T>
class Ref
{
void Decrement();
};
template <typename T>
class Collection {};
template <typename T>
class Ref<Collection<T>> {
void Decrement() {}
};
You can specialize a function template inside a class, i.e., this:
class Ref {
template <typename U> void Decrement();
};
or a function template inside a class template...
template <typename T>
class Ref {
template <typename U> void Decrement();
};
However, even then, a partial specialization, which is what you want to do, cannot be done for a function template; function templates can only be fully specialized for individual types, and never partially specialized, whereas class templates can be either partially or fully specialized.

Specialization of a class that uses Policy classes

I wrote the following:
//Policy Classes
template
<typename T>
struct CheckForZeroSpeed
{
};
template
<typename T>
struct NoCheck
{
};
//Specialization for one of the Policy Classes
template
<>
struct NoCheck<float>
{
};
//Class that uses Policy
template
<typename T,template <class C> class Policy>
class Base : public Policy<T>
{
};
//Inherited class that uses Policy
template
<typename T,template <class C> class Policy>
class Derived : public Base<T,Policy>
{
};
How can I declare a specialization of the Base class (let's say for the int type) and a specialization for the Derived class?
This also works:
template
<>
class Base<int,NoCheck>
{
};
But this is a specialization based both on the type and the policy, is it a way to have specialization based only one (type) of the two template parameters? Something like:
//not compile
template
<template <class C> class Policy>
class Base<int,Policy<T>>
{
};
Edit:
The correct is:
//Partial specialization based on the type
template
<template <class C> class Policy>
class Base<int,Policy>
{
};
//Partial specialization based on the Policy
template
<typename T>
class Base<T,NoCheck>
{
};

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