Template Specialization of a Single Method from a Templated Class

Template specialization of a single method from a templated class

As with simple functions you can use declaration and implementation.
Put in your header declaration:

template <>
void TClass<int>::doSomething(std::vector<int> * v);

and put implementation into one of your cpp-files:

template <>
void TClass<int>::doSomething(std::vector<int> * v) {
// Do somtehing with a vector of int's
}

Don't forget to remove inline (I forgot and thought this solution will not work :) ).
Checked on VC++2005

How to create specialization for a single method in a templated class in C++?

You can do what you want: http://ideone.com/oKTFPC

// Header

namespace My
{

template <typename T>
class MyClass {
public:
void dosome();
void doother();
};

template <typename T> void MyClass<T>::dosome() {}
template <typename T> void MyClass<T>::doother() {}

template<> void MyClass<char>::dosome();

}

// cpp or in header

template<>
void My::MyClass<char>::dosome() {
std::cout << "specialization" << std::endl;
}

or using alternate notation

namespace My {
template<>
void MyClass<char>::dosome() {
std::cout << "specialization" << std::endl;
}
}

specialize only (a part of) one method of a template class

You can use specialization like that (no need to specialize the whole class):

template<>
std::string C<string>::method3(string &t) {
// ...
std::string s = t;
// ...
return s;
}

Specializing single method in a big template class

In addition to the inheritance-based solution proposed by Torsten, you could use std::enable_if and default function template parameters to enable/disable certain specializations of the function.

For example:

template<typename T>
struct comparer
{
template<typename U = T ,
typename std::enable_if<std::is_floating_point<U>::value>::type* = nullptr>
bool operator()( U lhs , U rhs )
{
return /* floating-point precision aware comparison */;
}

template<typename U = T ,
typename std::enable_if<!std::is_floating_point<U>::value>::type* = nullptr>
bool operator()( U lhs , U rhs )
{
return lhs == rhs;
}
};

We take advantage of SFINAE to disable/enable the different "specializations" of the function depending on the template parameter. Because SFINAE can only depend on function parameters, not class parameters, we need an optional template parameter for the function, which takes the parameter of the class.

I prefer this solution over the inheritance based because:

  • It requires less typing. Less typing probably leads to less errors.
  • All specializations are written inside the class. This way to write the specializations holds all of the specializations inside the original class , and make the specializations look like function overloads, instead of tricky template based code.

But with compilers which have not implemented optional function template parameters (Like MSVC in VS2012) this solution does not work, and you should use the inheritance-based solution.

EDIT: You could ride over the non-implemented-default-function-template-parameters wrapping the template function with other function which delegates the work:

template<typename T>
struct foo
{
private:
template<typename U>
void f()
{
...
}

public:
void g()
{
f<T>();
}
};

Of course the compiler can easily inline g() throwing away the wrapping call, so there is no performance hit on this alternative.

Template member function specialization of a templated class without specifying the class template parameter

You can use a technique called tag dispatch and replace the template specialisations by function overloads.

template<typename>
struct Tag {};

template <class A>
struct C3
{
void f_impl(Tag<int>) const;
void f_impl(Tag<char>) const;
template<class B>
void f() const {
f_impl(Tag<B>{});
}
};

struct D { static int g(void){ return 999; } };

template <class A>
void C3<A>::f_impl(Tag<int>) const { std::cout<<A::g()+1<<std::endl; }

template <class A>
void C3<A>::f_impl(Tag<char>) const { std::cout<<A::g()+2<<std::endl; }

Then your call site looks exactly as you want:

 C3<D> c3; c3.f<int>();  // expect to see 1000
C3<D> c4; c4.f<char>(); // expect to see 1001

Full example here.

C++ - Template specialization by templated class

You can partially specialize the entire class template:

template <typename T>
struct sortedArray<smartPtr<T>> {
void insert(const smartPtr<T>& object) {
....
}

// everything else
};

Or you could explicitly specialize a single method:

An explicit specialization may be declared for a function template, a class template, a member of a class template or a member template.

as in:

template <>
void sortedArray<smartPtr<int>>::insert(const smartPtr<int>& object) {
...
}

But you cannot partially specialize just a single method.

Specialization of template class method

template <typename T>
class MyClass {
private:
T m_value;

private:
template<typename U>
void doSetValue (const U & value) {
std::cout << "template called" << std::endl;
m_value = value;
}

void doSetValue (float value) {
std::cout << "float called" << std::endl;
}

public:
void SetValue(const T &value) { doSetValue (value); }

};

or (partial template specialization):

template <typename T>
class MyClass
{
private:
T m_value;

public:
void SetValue(const T &value);

};

template<typename T>
void MyClass<T>::SetValue (const T & value) {
std::cout << "template called" << std::endl;
m_value = value;
}

template<>
void MyClass<float>::SetValue (const float & value) {
std::cout << "float called" << std::endl;
}

or, if you want the functions to have different signatures

template<typename T>
class Helper {
protected:
T m_value;
~Helper () { }

public:
void SetValue(const T &value) {
std::cout << "template called" << std::endl;
m_value = value;
}
};

template<>
class Helper<float> {
protected:
float m_value;
~Helper () { }

public:
void SetValue(float value) {
std::cout << "float called" << std::endl;
}
};

template <typename T>
class MyClass : public Helper<T> {
};

If I want to specialise just one method in a template, how do I do it?

You can provide a specialization for only that function outside the class declaration.

template <typename T> struct Node
{
// general method split
void split()
{
// implementation here or somewhere else in header
}
};

// prototype of function declared in cpp
void splitIntNode( Node & node );

template <>
void Node<int>::split()
{
splitIntNode( this ); // which can be implemented
}

int main(int argc, char* argv[])
{
Node <char> x;
x.split(); //will call original method
Node <int> k;
k.split(); //will call the method for the int version
}

If splitIntNode needs access to private members, you can just pass those members into the function rather than the whole Node.

Is it possible to specialize a method of a template class on another templated class?

Just using c++20 contrians:

template <typename V>
struct A {
void foo() { std::cout << "A<V>\n"; }

void foo() requires (std::same_as<V, std::vector<typename V::value_type>>) {
std::cout << "A<V<T>>\n";
}
};

Then this works:

A<int>{}.foo(); // call normal one
A<std::vector<int>>{}.foo(); // call specialized one

C++ - specialize function template on a templated class with a non type template parameter

Partial template specializations are not allowed for function templates.

Use SFINAE or class templates

template <class T>
struct validateType : std::false_type {};

template <class A, A val, class B>
struct validateType<Foo<A, val, B>> : std::true_type {};

Edit:

Is this supposed to work for template functions as well?

NO. Partial template specializations are not allowed for function templates.

for template function, use SFINAE.

For example, this sample check weather T is unsigned integer type(C++17).

template<typename T, std::enable_if_t<std::is_unsigned_v<T>, std::nullptr_t> = nullptr>
T foo(T n);
  • std::is_unsigned_v was added in C++17. before C++17, use std::is_unsigned<T>::value.

    https://en.cppreference.com/w/cpp/types/is_unsigned
  • std::enable_if_t was added in C++14. before C++14, use typename std::enable_if<con, T>::type.

    https://en.cppreference.com/w/cpp/types/enable_if
  • std::nullptr_t can hole only one value(nullptr) so that I use it for SFINAE enabler.

    (ja) https://qiita.com/kazatsuyu/items/203584ef4cb8b9e52462

However, in your case, you chould use class templates. It's simplest way to use class templates to check wether T is template class foo(BTW, not for template class foo, std::is_same is simplest way).



Related Topics



Leave a reply



Submit