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

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.

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

specializing template member function to work in a different way for a special template class

I have two classes class A and class B both of them are template classes for a member function in A I want it to act in a special way when the type of A is B
and in a normal way for any other types I don't know how to do this ?
template <class B>
class B
{
private:
T m;
public:
...... any member functions
}
template <class T>
class A
{
private:
T var;
public:
void doSomething();
};
template <class T>
void A<T>::doSomething(){...........//implementation}
template <class T>
void A<B<T>>::doSomething(){................//different implementation}
You can specialize A this way:
template <class T>
class A<B<T>> {
// ...
};
This is an instance of partial template specialization.
If you refuse to specialize the entire class, you can defer the work from A<T>::doSomething() to a function doSomethingForA<T>(A &) that would be partially specialized, and that would possibly be friend of A<T>.
Hope this solves your problem:
#include <iostream>
template <typename T>
struct B {};
template <typename T> struct A;
template <typename T>
void doSomething(T&) { std::cout << "General\n"; }
template <typename T>
void doSomething(A<B<T>>&) { std::cout << "Special\n"; }
template <typename T>
struct A {
void doSomething() {
::doSomething(*this);
}
};
int main()
{
A<int> general;
A<B<int>> special;
general.doSomething();
special.doSomething();
}

Explicitly specialized members need their containing class templates to be explicitly specialized as well

I read in many articles, that for class template when specializing
member template, the class that containing specialized member template also shall be explicitly specialized. Is there a point about it in standard and is there any reason to have such restriction?
I mean under the hood.
Why this is not allowed.
template <typename T>
class A
{
template <typename U>
void foo()
{}
};
template <typename T>
template <>
void A<T>::foo<int>()
{}
[temp.expl.spec]/16:
In an explicit specialization declaration for a member of a class
template or a member template that appears in namespace scope, the
member template and some of its enclosing class templates may remain
unspecialized, except that the declaration shall not explicitly
specialize a class member template if its enclosing class templates
are not explicitly specialized as well. [ Example:
template <class T1> class A {
template<class T2> class B {
template<class T3> void mf1(T3);
void mf2();
};
};
template <> template <class X>
class A<int>::B {
template <class T> void mf1(T);
};
template <> template <> template<class T>
void A<int>::B<double>::mf1(T t) { }
template <class Y> template <>
void A<Y>::B<double>::mf2() { } // ill-formed; B<double> is specialized
// but its enclosing class template A is not
— end example ]

How to specialize a templated member-function into a templated class in C++?

With regards to this question: How to create specialization for a single method in a templated class in C++? ...
I have this class:
template <typename T>
class MyCLass {
public:
template <typename U>
U myfunct(const U& x);
};
// Generic implementation
template <typename T>
template <typename U>
U MyCLass<T>::myfunct(const U& x) {...}
And I want to specialize myfunct for doubles.
This is what I do:
// Declaring specialization
template <>
template <typename T>
double MyCLass<T>::myfunct(const double& x);
// Doing it
template <>
template <typename T>
double MyCLass<T>::myfunct(const double& x) {...}
But it does not work.
That's not possible in C++. You can only specialise a member function template if you also specialise all enclosing class templates.
But anyway, it's generally better to overload function templates instead of specialising them (for details see this article by Herb Sutter). So simply do this:
template <typename T>
class MyCLass {
public:
template <typename U>
U myfunct(const U& x);
double myfunct(double x);
};

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