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.
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 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
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.
}
};
C++ specialize single method in template class
You can either change it to
template<typename U = T, typename std::enable_if<
!std::is_base_of<BaseClass, U>::value>::type* = nullptr>
void print_line()
{
std::cout << "Parameter of general Type T" << std::endl;
}
or
template<typename U = T>
typename std::enable_if<!std::is_base_of<BaseClass, U>::value, void>::type print_line()
{
std::cout << "Parameter of general Type T" << std::endl;
}
and the other one accordingly.
The idea behind both is to produce an error for one of the methods during the instantiation of the function templates. Due to the error, the corresponding method is not considered during overload resolution such that there is only one method (the one that did not produce the error) available, which will then be called. std::enable_if
is used to produce this error, because if its first parameter is false
it does not define a type
member so the function template cannot be instantiated and will be removed from overloading resolution.
Search for SFINAE for more detailed information.
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
How to specialize a template class method for a specific type?
You should make both the overloading of
print()
to function template (to make SFINAE working), otherwise the non-template function is always preferred.You should let
print()
taking its own template type parameter; type cheking shouldn't be performed on the class template parameterT
directly, function templates overload resolution and SFINAE are performed on the function templates themselves, the class template doesn't involve in.You can move the part of
std::enable_if
to the return type.You should change the order specified to
std::is_base_of
(i.e.std::is_base_of<Bar, X>
, notstd::is_base_of<X, Bar>
) if you want the type to beBar
or the derived class ofBar
.
e.g.
template <typename X = T>
typename std::enable_if<std::is_base_of<Bar, X>::value>::type print() {
t.print();
}
template <typename X = T>
typename std::enable_if<!std::is_base_of<Bar, X>::value>::type print() {
std::cout << t << std::endl;
}
LIVE
Related Topics
How to Enable Visual Styles Without a Manifest
Capturing a Time in Milliseconds
How to Securely Disconnect an Asio Ssl Socket
Gcc - How to Create a Mapfile of the Object File
Wrote to a File Using Std::Wofstream. the File Remained Empty
Why Do Reference Type Members Cause Implicitly-Declared Copy Assignment Operator to Be Deleted
C++ Concept That Requires a Member Function with an Outputiterator as Parameter
Opencv How to Select a Region of Image Irregularly with Mouse Event? C/C++
How to Use Non-Default Delimiters When Reading a Text File with Std::Fstream
Compiling a Win32 Gui App (Without a Console) Using Mingw and Eclipse
Image Scaling (Keepaspectratiobyexpanding) Through Opengl
Using Std:Fstream How to Deny Access (Read and Write) to the File