partial template specialization - c++

I have a scenario in which there is a template class
template<typename X, typename Y>
class Foo
{
typedef Y::NestedType Bar;
int A (Bar thing);
void B();
int C(X that);
// other stuff
};
and then I would like the A() method to have a different behavior when X is a given type (but B and C can stay the same, and the actual code actually has about 10 other methods, a few of which are quite lengthy and subject to frequent tweaking.. so I would rather avoid making a full-class specialization and copy&paste the full class implementation)
I went on and wrote:
template<typename T>
int Foo<MyType, T>::A(Bar thing);
but my compiler (clang 163.7.1) refused to even consider this as a template specialization of any sort.
Is there some syntax error hidden in the way I wrote the code, or is this coding style invalid C++? Unfortunately, even if other compilers do support the idiom, my company is stuck with clang.
Thanks for any help on this.

Use overloading
template<typename X, typename Y>
class Foo
{
// allows to wrap up the arguments
template<typename, typename>
struct Types { };
typedef Y::NestedType Bar;
int A (Bar thing) {
return AImpl(thing, Types<X, Y>());
}
void B();
int C(X that);
// other stuff
private:
template<typename X1, typename Y1>
int AImpl(Bar thing, Types<X1, Y1>) {
/* generic */
}
template<typename Y1>
int AImpl(Bar thing, Types<SpecificType, Y1>) {
/* special */
}
};
You cannot partially specialize a member of a class template. What you wrote would be the definition of a member function A of a partial specialization of the class template itself.

Related

Template argument deduction for member function pointers

It is known that template arguments can be pointers to member functions.
So I can write:
struct Bar
{
int fun(float x);
};
template <int (Bar::*FUN)(float)>
struct Foo
{ /*...*/ };
typedef Foo<&Bar::fun> FooBar;
But what if I want the the Bar type itself to be a template argument:
template <typename B, int (B::*FUN)(float)>
struct Foo
{ /*...*/ };
typedef Foo<Bar, &Bar::fun> FooBar;
Now, when I use it, I have to write Bar twice!
My question is: Is there a way to force the compiler to deduce the class type automatically?
The objective is for this to just work:
typedef Foo<&Bar::fun> FooBar;
typedef Foo<&Moo::fun> FooMoo;
Simple answer: no there isn't.
The problem is that for typedef Foo<&Bar::fun> FooBar; to work, the template would have to have a single non-type argument, but the type of that argument would be unknown when the template is being declared, which is not valid. On the other side, type deduction is never applied to the arguments of the template (only to the arguments to function templates, but those are the arguments to the function, not the template).
You probably should just write the class name in there. However, if you really want to avoid that you can use the evil magic of macros. The simple version is more dangerous:
#define TT(X) decltype(X), X
template<typename T,T t>
struct Foo
{ /* ... */ };
struct Bar {
int fun(float) {}
};
int main() {
Foo<TT(&Bar::fun)> f;
}
This will accept any kind of non-type template parameter, and you may encounter hard-to-understand errors if the Foo implementation only works with pointers-to-member.
To make it a bit safer you need a metafunction that tells you the class name:
template<typename T> struct member_ptr_traits;
template<typename Class,typename Ret,typename... Args>
struct member_ptr_traits<Ret (Class::*)(Args...)>
{
typedef Class class_type;
typedef Ret return_type;
};
#define TT(X) member_ptr_traits<decltype(X)>::class_type , X
template<typename T,int (T::*FUN)(float)>
struct Foo
{ /* ... */ };
struct Bar {
int fun(float) {}
};
int main() {
Foo<TT(&Bar::fun)> f;
}
Also both of these use C++11 so they won't work with old compilers. This simple version can be rewritten to use the old typeof or similar compiler extensions. Rewriting the safer version requires simulating variadic templates.

Template classes with specialised constructors

Consider the following contrived example of a templated array definition:
template <typename t, unsigned int n> class TBase
{
protected:
t m_Data[n];
//...
};
template <typename t, unsigned int n> class TDerived : public TBase<t, n>
{
TDerived()
{
}
};
I can specialize this type to provide a non-default constructor for an array of length 2 as follows:
template <typename t> class TDerived<t, 2> : public TBase<t, 2>
{
public:
TDerived(const t& x0, const t& x1)
{
m_Data[0] = x0;
m_Data[1] = x1;
}
};
int main()
{
TDerived<float, 2> Array2D_A(2.0f, 3.0f); //uses specialised constructor
TDerived<float, 3> Array3D_A; //uses default constructor
return 0;
}
Is there some other way I can create a class that has different constructor options constrained against template parameters at compile-time without the requirement for a complete class specialisation for each variation?
In other words, is there some way I can have specialised constructors in the TBase class without the need for the intermediary step of creating TDerived whilst preserving the functionality of TBase?
I think deriving your class from a base class is not relevant to the question here, that's a mere implementation detail. What you really seem to be after is if there's a way to partially specialize member functions, like the constructor. Do you want something like this?
template <typename T, int N> class Foo
{
Foo(); // general
template <typename U> Foo<U, 2>(); // specialized, NOT REAL CODE
};
This doesn't work. You always have to specialize the entire class. The reason is simple: You have to know the full type of the class first before you even know which member functions exist. Consider the following simple situation:
template <typename T> class Bar
{
void somefunction(const T&);
};
template <> class Bar<int>
{
double baz(char, int);
};
Now Bar<T>::somefunction() depends on T, but the function only exists when T is not int, because Bar<int> is an entirely different class.
Or consider even another specialization template <> class Bar<double> : public Zip {}; -- even the polymorphic nature of a class can be entirely different in a specialization!
So the only way you can provide specializations new declarations of members, including constructors, is by specializing the entire class. (You can specialize the definition of existing functions, see #Alf's answer.)
There are basically two options I see for this:
Use a variadic function for construction (ie. "..." notation), you can use the value n inside that function to get your arguments from the stack. However, the compiler will not check at compile time if the user provides the correct number of arguments.
Use some serious template magic to allow a call chaning initialization, that would look like this: vector(2.0f)(3.0f). You can actually build something that at least ensures the user does not provide too many arguments here. However tha mechanism is a little more involved, I can assemble an example if you want.
You can always specialize a member, e.g.
#include <stdio.h>
template< class Type >
struct Foo
{
void bar() const
{ printf( "Single's bar.\n" ); }
};
template<>
void Foo< double >::bar() const
{ printf( "double's bar.\n" ); }
int main()
{
Foo<int>().bar();
Foo<double>().bar();
}
But you want effectively different signatures, so it's not directly a case of specializing a member.
One way forward is then to declare a constructor with a single argument, of a type dependent on the template parameters.
Then you can specialize that, as you want.
Cheers & hth.,
Since constructor is a function, you need to fully specialize the containing class to address your specific problem. No way out.
However, functions cannot be partially specialized (in all compilers). So suppose if you know that you need n = 2 when t = int or double then following is one alternative.
template<>
TDerived<int,2>::TDerived()
{
//...
}
template<>
TDerived<double,2>::TDerived()
{
//...
}
and so on.
[Note: If you use MSVC, then I think it supports partial specialization; in that case you can try:
template<typename t>
TDerived<t,2>::TDerived()
{
//...
}
though, I am not sure enough for that.]
You could give the most common definitions in the non-specialized class and static_assert (BOOST_STATIC_ASSERT for non C++0x) on the array length. This could be considered a hack but is a simple solution to your problem and safe.
template<typename T, unsigned int n>
struct Foo {
Foo(const T& x) { static_assert(n == 1, "Mooh!"); }
Foo(const T& x1, const T& x2) { static_assert(n == 2, "Mooh!"); }
};
The "evil" way would be variadic arguments.
template<typename T, unsigned int n>
struct Foo {
Foo(...) {
va_list ap;
va_start(ap, n);
for(int j=0; j < n; ++j)
bork[j] = va_arg(ap, T);
va_end(ap);
}
};
Then there is also C++0x and the good old make_something trick which is more difficult then one would think.
template<typename... T, unsigned int n>
Foo<T, n> make_foo(T&&...) {
// figure out the common_type of the argument list
// to our Foo object with setters or as a friend straight to the internals
Foo< std::common_type< T... >::type, sizeof(T) > foo;
// recursive magic to pick the list apart and assign
// ...
return foo;
}

What is the meaning of template<> with empty angle brackets in C++?

template<>
class A{
//some class data
};
I have seen this kind of code many times.
what is the use of template<> in the above code?
And what are the cases where we need mandate the use of it?
template<> tells the compiler that a template specialization follows, specifically a full specialization. Normally, class A would have to look something like this:
template<class T>
class A{
// general implementation
};
template<>
class A<int>{
// special implementation for ints
};
Now, whenever A<int> is used, the specialized version is used. You can also use it to specialize functions:
template<class T>
void foo(T t){
// general
}
template<>
void foo<int>(int i){
// for ints
}
// doesn't actually need the <int>
// as the specialization can be deduced from the parameter type
template<>
void foo(int i){
// also valid
}
Normally though, you shouldn't specialize functions, as simple overloads are generally considered superior:
void foo(int i){
// better
}
And now, to make it overkill, the following is a partial specialization:
template<class T1, class T2>
class B{
};
template<class T1>
class B<T1, int>{
};
Works the same way as a full specialization, just that the specialized version is used whenever the second template parameter is an int (e.g., B<bool,int>, B<YourType,int>, etc).
template<> introduces a total specialization of a template. Your example by itself isn't actually valid; you need a more detailed scenario before it becomes useful:
template <typename T>
class A
{
// body for the general case
};
template <>
class A<bool>
{
// body that only applies for T = bool
};
int main()
{
// ...
A<int> ai; // uses the first class definition
A<bool> ab; // uses the second class definition
// ...
}
It looks strange because it's a special case of a more powerful feature, which is called "partial specialization."
Doesn't look right. Now, you might have instead written:
template<>
class A<foo> {
// some stuff
};
... which would be a template specialisation for type foo.

Partial Specialization of Operator()

One of my classes declares a templated function:
template<class A, class B>
A do_something(const std::vector<B> &data)
which I'd like to partially specialize on typename A. B is a family of types that implement a pretty minimal interface, and we use a lot of them, so I'd like my specialization to be generic on B. I suspect this is doubly vexing as typename A is used only as the return type.
From the internet, I've gleaned that I can't partially specialize a function, so I've created a class as follows:
template<class A, class B>
class do_something_implementation {
public:
do_something_implementation(const std::vector<B> &data_) {
data = data_;
}
int do_something_implementation<int, B>::operator()() {
/* Complicated algorithm goes here... */
}
double do_something_implementation<double, B>::operator()() {
/* Different complicated algorithm goes here... */
}
private:
std::vector<B> data;
}
When I try to compile that (using Visual Studio 2008), the compiler crashes (!) and I get the following error:
fatal error C1001: An internal error has occurred in the compiler.
I assume this is my problem and not the compiler's. Is there a better way to express the partial specialization I'm aiming for?
Usually, it goes like this:
template <typename A, typename B>
struct DoSomethingHelper
{
static A doIt(const std::vector<B> &data);
};
template <typename B>
struct DoSomethingHelper<double, B>
{
static double doIt(const std::vector<B> &data) { ... }
};
template <typename B>
struct DoSomethingHelper<int, B>
{
static int doIt(const std::vector<B> &data) { ... }
};
template<class A, class B>
A do_something(const std::vector<B> &data)
{ return DoSomethingHelper<A, B>::doIt(data); }
Now that you've seen the classic forward to static method, there is actually another way when the type for which to specialize is "complete".
You may not be able to partially specialize a function, but you can perfectly overload it.
template <typename A, typename B>
A do(std::vector<B> const& data) { return this->doImpl(data, (A*)0); }
template <typename A, typename B>
A doImpl(std::vector<B> const& B, A*) { // generic implementation }
template <typename B>
int doImpl(std::vector<B> const& B, int*) { // int implementation }
template <typename B>
double doImpl(std::vector<B> const& B, double*) { // double implementation }
The trick is to pass an "unused" argument to doImpl for the sole purpose of actually selecting the right implementation (thanks to overload resolution).
Here I simply chose to pass (A*)0, because this does not involve A's constructor (in case it's non trivial).
This dispatch idiom is what is used in the STL to implement some algorithm with better efficiency for some iterator categories (for example, std::distance is O(1) for random iterators).
I find it much more lightweight that using a helper class with static methods and partial specializations... but maybe that's just me :)
People typically just forward to a static implementation.
template<class A, class B> class X;
template<class A, class B> friend class X;
template<class A, class B> class X {
public:
static A do_something(class_type* not_this, const std::vector<B>& data) {
//...
}
};
// partially specialize
template<class A, class B>
A do_something(const std::vector<B> &data) {
return X<A, B>::do_something(this, data);
};
Not a solution to your problem (there are a couple already there), but some of the things that are wrong in your code:
You are missing a struct or class keyword in the template class declaration:
template <typename A, typename B> struct do_something_implementation {
// ^^^^^^
Inside the class definition, member functions must not use a qualified name, regardless of whether the class is a template or not:
class A {
void A::foo() {} // Error, should be: void foo() {}
};
Member template specializations cannot appear inside the class definition, but at the namespace level:
class B {
template <typename T> void foo( T );
};
template <> void B::foo<int>( int ) {}
template <> void B::foo<double>( double ) {}
Plus on your case, the member function is not a template, but rather a non-templated member function (the template is the containing class, not the function itself). What your code is effectively trying to do is defining other class' member functions inside the general template, kind of trying to do.
Overall there was enough errors to make parsing the code almost impossible for the compiler to identify what you were trying to do and provide a good error message, but still, it should have provided any error message pointing to the first line that you copied instead of chocking to death.

How can one avoid duplicating class template specification for each member function?

If I have a template class specification like so,
template <typename T>
class MyClass {
public:
void fun1();
// ...
void funN();
};
template <typename T>
void MyClass<T>::fun1() {
// definition
}
// ...
template <typename T>
void MyClass<T>::funN() {
// definition
}
If I change the class template to something else, say I add an extra parameter:
template <typename T, typename U>
class MyClass {
// ...
};
Then I have to change each function definition (fun1, ..., funN) to agree with the class template specification:
template <typename T, typename U>
void MyClass<T,U>::fun1() { //... }
Are there any strategies for avoiding this? Could I use macros e.g.
#define DFLT_TEMPLATE template<typename T, typename U>
#define DFLT_CLASS class<T,U>
DFLT_TEMPLATE
void DFLT_CLASS::fun1() { // ... }
Or is this considered bad practice?
To me, the benefits of using a macro here are far overshadowed by the drawbacks. Yes, if you use a macro then if you ever need to add an additional template parameter, you'll only need to make a single modification. But anyone else reading your code is probably going to vomit.
I mean, are you going to do this for every template you have? Your code will become infested with ugly macros.
How many member functions do you have that this is an issue?
I think either they are small enough to be defined within the class template or the adaption of their algorithms to an additional template parameter would by far outweigh the replacement of those function headers.
Also, your editor ought to do this for you in no time anyway.
yes you could but don't forget to use "#undef DFLT_TEMPLATE" and "#undef DFLT_CLASS" at the end of file to avoid compiler warnings if your project have several templates with same macros definitions
Inheritation is better than macro.
If you want to change only a few functions and variables, make the specialized class inherit a common class that provides common functions/variables.
As far as possible, put the function definitions in the class template definition. It's a template, so unless you're using Comeau compiler, it's not as if they're going to be off in a different TU.
If the functions use something which is defined in between the class definition and the function definition, then you can play tricks to make that thing dependent on a template parameter even when "really" it isn't. For example:
template <typename T>
struct Foo {
void usebar();
};
struct Bar {
int a;
Foo<int> circularity; // circular dependency between Foo and Bar
Bar() : a(3) {}
};
template <typename T> void Foo<T>::usebar() {
Bar b;
std::cout << b.a << "\n";
}
Becomes:
// we only have to write "same" once
template <typename T, typename U>
struct same {
typedef U type;
};
struct Bar;
template <typename T>
struct Foo {
void usebar() {
typename same<T,Bar>::type b;
std::cout << b.a << "\n";
}
};
struct Bar {
int a;
Foo<int> circularity; // circularity gone
Bar() : a(3) {}
};
Or actually in this case just:
struct Bar;
template <typename T, typename B = Bar>
struct Foo {
void usebar() {
B b;
std::cout << b.a << "\n";
}
};
struct Bar {
int a;
Foo<int> circularity;
Bar() : a(3) {}
};
All cases support the following code:
int main() {
Foo<int> f;
f.usebar();
}
I would consider this approach bad practice. What you are complaining about is that you have changed your design (you need an extra template parameter) and now want a kludge to save on typing?
Introducing macros is going to decrease the readability of your code. Preprocessor definitions certainly have their place, but personally I'd never advocate one on the grounds that I can't be bothered to change my functions.
There are probably some (more or less bad) workarounds, but you definitely point out a " missing" feature of C++: class namespace extension.
Some people already proposed to extend C++ in this way:
http://www.lrde.epita.fr/dload//20080709-Seminar/ordy-classnamespaces.pdf
namespace foo
{
class bar
{
typedef int baz_t;
baz_t my_method ();
};
}
namespace class foo::bar
{
baz_t my_method ()
{
// ...
}
}
--
Using a macro is not a good idea (usual things about macros ....).
I would prefer, at worst, write function members definitions inline in this case, or even better use an editor than can help you easily update your class definition.
Macros are bad because they let you write code editing functions where you are supposed to write programs.
If you want to edit code, use your editor (sed, M-x replace-*, Find&Replace ...)