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, usestd::is_unsigned<T>::value
.
https://en.cppreference.com/w/cpp/types/is_unsignedstd::enable_if_t
was added in C++14. before C++14, usetypename std::enable_if<con, T>::type
.
https://en.cppreference.com/w/cpp/types/enable_ifstd::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
Move or Named Return Value Optimization (Nrvo)
Can't Overload Operator<< as Member Function
Compiling External C++ Library for Use with iOS Project
Generating M Distinct Random Numbers in the Range [0..N-1]
How to Access Private Data Members Outside the Class Without Making "Friend"S
How to Tell If the C Function Atoi Failed or If It Was a String of Zeros
Get Function Pointer from Std::Function When Using Std::Bind
"Symbol(S) Not Found for Architecture X86_64" on Qtcreator Project
C++ Vector, What Happens Whenever It Expands/Reallocate on Stack
Converting Bool to Text in C++
Is Volatile Bool for Thread Control Considered Wrong
Why Does Storing References (Not Pointers) in Containers in C++ Not Work