The class Widget has some functions that apply for all parameter types (common functions) and other functions that need to be specialized for given types (the uncommon functions).
g++ insists that the specialization for Widget should also define common_fn() and not just uncommon_fn(), but that defeats the purpose of using specialization in the first place. How can one avoid repeating common_fn()?
#include <cassert>
template<typename Type> struct Widget
{
Widget() {}
char common_fn() { return 'a'; }
int uncommon_fn() { return 1; }
};
template<> struct Widget<char>
{
Widget() {}
int uncommon_fn() { return 2; }
};
int main()
{
Widget<char> WidgetChar;
assert( WidgetChar.common_fn() == 'a' ); // Error
assert( WidgetChar.uncommon_fn() == 2 );
}
begin-edit
to Alf:
I am unable to use
template<> int Widget<char>::uncommon_fn() { return 2; }
because some of the uncommon functions need to return a trait type (and so it was excessive to simplify by making the actual type primitive).
Or is there in fact a way to make the compiler recognize typename Foo::Bar
when writing
struct Foo { typedef FooBar Bar; };
template<> typename Foo::Bar Widget<Foo>::uncommon_fn() { return ....; }
?
end-edit
begin-edit2
to iammilind:
That's interesting, but I am unable to use derivation from Widget (or the possibly clearer solution of refactoring the common parts into a parent class GeneralWidget) for the same reason. The common parts are not entirely common. Their declarations and their definitions look the same, but because they use traits they are at the end quite different.
end-edit2
#include <assert.h>
template<typename Type> struct Widget
{
Widget() {}
char common_fn() { return 'a'; }
int uncommon_fn() { return 1; }
};
template<>
int Widget<char>::uncommon_fn() { return 2; }
int main()
{
Widget<char> WidgetChar;
assert( WidgetChar.common_fn() == 'a' ); // OK
assert( WidgetChar.uncommon_fn() == 2 );
}
First off, this isn't really a supported thing to do in C++. Template specialization requires you to redefine all the methods, unfortunately.
You can put your common methods in a base class, and then include them by inheritance, although my own experience with that has been a mixed bag (a function in the parent class just doesn't behave quite the same way as a function in the child class in all cases; friendship works strangely, and if the base class is also a template, you have to fully specify it whenever you wish to use any of its members [except on MS compilers]. Operators never work quite as well either). You can do it by copy-pasting your common methods, which is precisely what you're trying to avoid. Or, as a compromise on copy-pasting, you can have the compiler do your copy-pasting for you:
template<> struct Widget<char>
{
#include "Widget_common.hpart"
int uncommon_fn() { return 2; }
};
Then you make a file called "Widget_common.hpart" that contains
// This file contains common functions for the Widget<> template, and will be #included
// directly into that template; it should not be included as a standalone header.
char common_fn() { return 'a'; }
You can also just use the standard .h extension, I suppose. This is definitely preprocessor abuse, but it does what you ask for, avoids the template inheritance headaches (and they really are quite painful), and lets you keep only a single copy of your common code. And if anyone wants to criticize what a horrible kludge this is, do so with an improved solution ;).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With