Template Specialization of Particular Members

How to specialize only some members of a template class?

Consider moving common parts to a base class:

template <typename T>
struct ABase
{
void f1();
};


template <typename T>
struct A : ABase<T>
{
void f2();
}


template <>
struct A<int> : ABase<int>
{
void f2();
};

You can even override f1 in the derived class. If you want to do something more fancy (including being able to call f2 from f1 code in the base class), look at the CRTP.

Partial specialization of specific member functions

Tag-dispatch the call to update:

template <typename> struct tag {};

template <typename T1, typename T2>
class B
{
public:
void update()
{
return update(tag<B>());
}

private:
template <typename U1>
void update(tag<B<U1, int> >)
{
// specialization
}

template <typename U1, typename U2>
void update(tag<B<U1, U2> >)
{
// normal
}
};

DEMO

c++ template partial specialization member function

You cannot partially specialize only a single member function, you must partially specialize the whole class. Hence you'll need something like:

template <typename T>
class Object<T, 0>
{
private:
T m_t;
Object();
public:
Object(T t): m_t(t) {}
T Get() { return m_t; }
Object& Deform()
{
std::cout << "Spec\n";
m_t = -1;
return *this;
}
};

explicit specialization of template class member function

It doesn't work that way. You would need to say the following, but it is not correct

template <class C> template<>
void X<C>::get_as<double>()
{

}

Explicitly specialized members need their surrounding class templates to be explicitly specialized as well. So you need to say the following, which would only specialize the member for X<int>.

template <> template<>
void X<int>::get_as<double>()
{

}

If you want to keep the surrounding template unspecialized, you have several choices. I prefer overloads

template <class C> class X
{
template<typename T> struct type { };

public:
template <class T> void get_as() {
get_as(type<T>());
}

private:
template<typename T> void get_as(type<T>) {

}

void get_as(type<double>) {

}
};

C++ template partial specialization - specializing one member function only

Second solution (correct one)

template <typename T>
class foo
{
public:
void addSome (T o) { printf ("adding that object..."); }
void deleteSome(T o) { deleteSomeHelper<T>()(o); }
protected:
template<typename TX>
struct deleteSomeHelper { void operator()(TX& o) { printf ("deleting that object..."); } };
template<typename TX>
struct deleteSomeHelper<TX*> { void operator()(TX*& o) { printf ("deleting that PTR to an object..."); } };
};

This solution is valid according to Core Issue #727.


First (incorrect) solution: (kept this as comments refer to it)

You cannot specialize only part of class. In your case the best way is to overload function deleteSome as follows:

template <typename T>
class foo
{
public:
void addSome (T o) { printf ("adding that object..."); }
void deleteSome (T o) { printf ("deleting that object..."); }
void deleteSome (T* o) { printf ("deleting that object..."); }
};

Template specialization with only one parameter

It's called a partial template specialization:

template <class T, unsigned Capacity>
struct Collection {

};

template <unsigned Capacity>
struct Collection<Pair, Capacity> {
// Specialize
};

One thing to note is that you cannot partially specialize a single function. You have to specialize the whole class template, which is irritating if the class template is long. Another quick-and-dirty way of doing this if you want to specialize a single function would be to just use a "compile-time if":

#include <type_traits>

template <class T, unsigned Capacity>
struct Collection {
void display() const {
if constexpr (std::is_same_v<T, Pair>) {
// pair implementation
} else {
// general implementation
}
}
};

Or, as a more clean solution, try moving the whole thing out of the class and add a simple overload:

// Free-standing overloads:

template <class T, unsigned Capacity>
void diplay(Collection<T, Capacity> const& c) { /* ... */ }

template <unsigned Capacity>
void display(Collection<Pair, Capacity> const& c) { /* ... */ }


// The member function delegates the work to
// the overloaded functions. No template specialization
// is involved:

template <class T, unsigned Capacity>
struct Capacity {
void display() const {
display(*this); // calls the correct overload.
}
};


Related Topics



Leave a reply



Submit