Is it possible to specialize a few functions for a template class without specializing the whole thing?
For example:
template <typename T>
struct A {
int foo();
};
template <typename T>
int A<T>::foo() { return 1;}
template <>
struct A<int> {
int bar() { return 2; };
};
main() {
A<int> a;
a.foo(); //1
a.bar(); //2
A<double> b;
b.foo(); //1
b.bar(); // ERROR
}
Or something similar?
No. But there is a way around it.
Hand off the logic to a free function template specialisation from within the template class method.
template<class T>
int delegated_foo() {
return 1;
}
// now specialise
template<>
int delegated_foo<int>() {
return 2;
}
template <typename T>
struct A {
int foo() {
return delegated_foo<T>();
}
};
To answer the comment - if you want to partially specialise a class, you can delegate common logic in to a template base class.
template<class T>
struct a_common {
void common_function() {
// define here. Compiler will generate 1 for each T
}
};
template<class T>
struct A : public a_common<T>
{
int something_i_might_specialise();
};
Related
In a class B inheriting from class A, it's possible to use a using declaration to bring members of A into B, even templates, like this:
struct A {
template <typename T>
void foo();
};
struct B : private A {
using A::foo;
};
But can it be done for conversion templates?
struct A {
template <typename T>
operator T();
};
struct B : private A {
using A::operator /* ??? */;
};
There seems to be no way of referring to the template by name, but I would love to be proven wrong or get some clarification.
As a workaround, you can cast to the base class and convert it explicitly:
struct A {
template <typename T>
operator T() {
return T{};
}
};
struct B : private A {
template <class T>
operator T() {
return static_cast<T>(static_cast<A&>(*this));
}
};
int main() {
A a;
B b;
int i_a = a;
int i_b = b;
}
The program below does not compile if I uncomment the line containing foo<double>(), because B<double> depends on A<double>, which is an incomplete type.
#include <iostream>
using namespace std;
template <class T> struct A; // forward declaration (incomplete)
template <> struct A<int> {}; // specialized for int
template <class T> struct B : A<T> { int foo() {return 0;} }; // derived class, general definition inherits from A
template <> struct B<bool> { int foo() {return 1;} }; // derived class, does not inherit from A
template <class T> int foo() { B<T> b; return b.foo(); } // to be called if B<T> is valid
int main()
{
cout << foo<int>() << "\n"; // print 0
cout << foo<bool>() << "\n"; // print 1
// cout << foo<double>() << "\n"; // this line would generate a compile error
}
I would like a way to overload the function foo so that if B<T> is not a valid type, then an alternative version of the function foo is called.
I.e. I would like to have a way to define the overload
template <class T> int foo() { return -1; } // to be called if B<T> is not valid
I can also wrap the function foo inside a struct, if that helps. Is there a way to do that in C++03?
Remembering your analogue question and the answer from Quentin, I see that the problem is that B<T> can be (apparently) complete when A<T> is incomplete.
The only way I see (sorry: only C++11 at the moment) is impose that the general B<T> is defined only if A<T> is defined (trasforming it in a partial specialization); in the following way
template <typename T, bool = is_complete<A<T>>::value>
struct B;
template <typename T>
struct B<T, true> : A<T>
{ int foo() {return 0;} };
template <>
struct B<bool>
{ int foo() {return 1;} };
If you can modify B in this way, the solution is simple (using again the is_complete developed by Quentin).
The following is a working example
#include <iostream>
#include <type_traits>
template <typename T, std::size_t = sizeof(T)>
std::true_type is_complete_impl(T *);
std::false_type is_complete_impl(...);
template <typename T>
using is_complete = decltype(is_complete_impl(std::declval<T*>()));
template <typename>
struct A;
template <>
struct A<int>
{ };
template <typename T, bool = is_complete<A<T>>::value>
struct B;
template <typename T>
struct B<T, true> : A<T>
{ int foo() {return 0;} };
template <>
struct B<bool>
{ int foo() {return 1;} };
template <typename T>
typename std::enable_if<true == is_complete<B<T>>::value, int>::type foo()
{ B<T> b; return b.foo(); }
template <typename T>
typename std::enable_if<false == is_complete<B<T>>::value, int>::type foo()
{ return 2; }
int main()
{
std::cout << foo<int>() << "\n"; // print 0
std::cout << foo<bool>() << "\n"; // print 1
std::cout << foo<double>() << "\n"; // print 2
}
How to take care of the repetitions below for the Object::func() definitions without using macros?
template <int N> struct Object {};
template <> struct Object<0> {
// special stuff
void func();
};
template <> struct Object<1> {
// special stuff
void func();
};
template <> struct Object<2> {
// special stuff
void func();
};
template <int N> struct Thing {};
void Object<0>::func() {
Thing<0> a;
// do stuff with a
}
void Object<1>::func() {
Thing<1> a;
// do exact same stuff with a
}
void Object<2>::func() {
Thing<2> a;
// do exact same stuff with a
}
Private inheritance, with the base having template int N? Meta-template stuff? CRTP? I can't figure it out. Note that
// special stuff
means that the template specializations are necessary--I'm just not showing how they are specialized. I'm only showing the one function func() that are almost identical to all of them.
Using inheritance you can avoid specialization for the common code. How about:
template <int N> struct ObjectBase {
void func();
};
template <int N> struct Thing {};
template <int N>
void ObjectBase<N>::func() {
Thing<N> a;
// do stuff with a
}
template <> struct Object<0>: private ObjectBase<0> {
// special stuff
};
template <> struct Object<1>: private ObjectBase<1> {
// special stuff
};
template <> struct Object<2>: private ObjectBase<2> {
// special stuff
};
For your question, my solution is to use template template parameters to define your template class, I feel this is the way to avoid re-define common things over and over.
Below is the code that I just coded and tested in Visual Studio 2013:
#include <iostream>
template <int N> struct Thing { int x; Thing() : x(N) {}; };
template <int N, template<int N> class T> struct Object { void func(); };
template <int N, template<int N> class T> void Object<N, T>::func()
{
T<N> a;
std::cout << a.x << std::endl;
};
int main()
{
Object<0, Thing> obj0;
Object<11, Thing> obj11;
Object<22, Thing> obj22;
obj0.func();
obj11.func();
obj22.func();
return 0;
}
This code will print:
0
11
22
My problem is as follows.
This is my method:
template<class T>
T my_function();
These specializations work ok:
template<>
int my_function(); //my_function<int>();
template<>
float my_function(); //my_function<flot>();
...
But these don't:
1.
template<>
template<class T>
std::list<T> my_function(); //my_function<std::list<class T> >();
2.
template<class T>
template<>
std::vector<T> my_function(); //my_function<std::vector<class T> >();
I get the error:
too many template-parameter-lists
so my question is:
How do I specialize a template with a template class?
You cannot partially specialize a function template, but you can for class.
So you may forward the implementation to a class as the following:
namespace detail {
template <typename T> struct my_function_caller { T operator() () { /* Default implementation */ } };
template <> struct my_function_caller<int> { int operator() () { /* int implementation */ } };
template <> struct my_function_caller<float> { float operator() () { /* float implementation */ } };
template <typename T> struct my_function_caller<std::list<T>> { std::list<T> operator() () { /* std::list<T> implementation */ } };
template <typename T> struct my_function_caller<std::vector<T>> { std::vector<T> operator() () { /* std::vector<T> implementation */ } };
}
template<class T>
T my_function() { return detail::my_function_caller<T>()(); }
You can't partially specialize a function, if you declare
template<class T>
T my_function() {
....
}
template<class T>
std::list<T> my_function() {
....
}
and try to call the first with
my_function<int>();
since partial specializations are not allowed for functions these declarations will be conflicting (those are actually two different declarations, and what's worse: they both match for that instantiation).
What you can do is wrap your function into a class or a struct that can handle partial specializations for it:
#include <iostream>
#include <list>
using namespace std;
template<class T> struct funWrapper {
T my_function() {
cout << "normal" << endl;
return 0;
}
};
template<class T> struct funWrapper<std::list<T>> {
std::list<T> my_function() {
cout << "stdlist";
return std::list<T>();
}
};
int main() {
funWrapper<int> obj;
obj.my_function();
funWrapper<std::list<int>> obj2;
obj2.my_function();
return 0;
}
http://ideone.com/oIC2Hf
I have a class template, let's call it A, which has a member function abc():
template <typename T>
class A{
public:
T value;
void abc();
};
I can implement the member function abc() outside the class declaration, using the following syntax:
template <typename T>
void A<T>::abc()
{
value++;
}
What I want to do is to create a template specialization for this class, let's say int.
template <>
class A<int>{
public:
int value;
void abc();
};
The question is: what is the correct syntax to implement abc() for the specialized class?
I tried using the following syntax:
template <>
void A<int>::abc()
{
value += 2;
}
However this doesn't compile.
void A<int>::abc()
{
value += 2;
}
since A<int> is explicit specialisation of A<T>.
http://liveworkspace.org/code/982c66b2cbfdb56305180914266831d1
n3337 14.7.3/5
Members of an explicitly specialized class template are
defined in the same manner as members of normal classes, and not using the template<> syntax.
[ Example:
template<class T> struct A {
struct B { };
template<class U> struct C { };
};
template<> struct A<int> {
void f(int);
};
void h() {
A<int> a;
a.f(16);
}
// A<int>::f must be defined somewhere
// template<> not used for a member of an
// explicitly specialized class template
void A<int>::f(int) { /∗ ... ∗/ }
Remove the template<>:
void A<int>::abc()
{
value += 2;
}