This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 8 years ago.
I looked around for a good solution to avoid code duplication on each spezialization of a template class.
Here is an example code:
template<class T>
class C
{
int foo();
}
Now the definition for defaults:
template<class T>
C<T>::foo() { return 0; }
Now the spezailization for special templates
template<> C<int>::foo() { ... do a lot of stuff and return n .... }
template<> C<double>::foo() { ... do a lot of stuff and return n .... }
template<> C<int>::foo() { ... do a lot of stuff and return n .... }
Right now I have to duplicate the code for the spezailization. But in general it's the same code.
My questions is:
What is the best solution to avoid code duplication here and how can I hide the implementation ? Maybe by using a noname-namespace or an impl-namespace ?
Kind regards,
Peter
You can do as with any other class: extract the boilerplate code to another (private) function in the template class and call this one in your specializations.
template<class T>
class C
{
int foo();
void bar() { /* does lot of stuff ... */ }
};
template<> int C<int>::foo() { bar(); return n .... }
template<> int C<double>::foo() { bar(); return n .... }
and how can I hide the implementation ? Maybe by using a noname-namespace or an impl-namespace ?
It's not really possible to hide the implementation of template code, by means of having a compilation unit specific unnamed namespace.
If your intend mainly is to get a cleaner readable template header file, you can factor out the implementation to another included file. These are often named .tcc or .icc, there are samples for this technique in most of the c++ implementation standard header files.
One way to avoid duplicating code is to use a base class to handle generic implementation:
template <class T>
class base_C
{
void generic_foo(){...}
};
template <>
class C <SpecialType> : base_C<SpecialType>
{
void foo()
{
SpecialType::custom_foo();
base_C<SpecialType>::generic_foo();
}
};
The idea begind this is to split foo into more generic parts and put them into base_C. With this each specialization of C::foo will have a minimal amount of custom code.
Related
Hello template wizards,
I have been concocting a utility template which has one problem left to be solved, but cannot seem to figure it out. The code in this post is a simplification of the code in question, which exhibits the same issue.
Suppose you have a template specialisation as shown below.
enum class Pets { Dog, Cat, Bird };
template <Pets variant>
class Animal;
template <>
class Animal<Pets::Cat> {
void Sound();
};
template <>
class Animal<Pets::Dog> {
void Sound();
};
template <>
class Animal<Pets::Bird> {
void Sound();
};
void Animal<Pets::Cat>::Sound() { printf("Meow!\n"); }
void Animal<Pets::Dog>::Sound() { printf("Woof!\n"); }
void Animal<Pets::Bird>::Sound() { printf("Peep!\n"); }
And then I ruin everything by saying that I might not declare the specialisation of Animal<Pets::Bird>. The latter definition of ::Sound() will fail to compile, as the type doesn't exist. Now, this seems to beg for a SFINAE solution, to me, as we have an unwanted method implementation of a type that we don't want to exist.
I'd like the compiler to simply ignore that last method definition instead of failing compilation, without changing the method signature — that is, I don't want to make the method itself a template.
Do you have any suggestions on how to make this work?
You can’t do this: SFINAE is about overload resolution, and while it also supports the very similar case of selecting a partial specialization, it’s not a general conditional compilation technique. You can use the preprocessor, of course, and you can do tricks like declaring the unwanted function private so that it “doesn’t exist”, but you can’t define a function that just is never mentioned.
I did manage to conjure up a solution, which quite neatly just declares a catch-all, for those types are to be discarded — not quite what I asked for, but closer toward the goal.
This, at least, takes care of the definitions of methods that would otherwise fail compilation.
enum class Pets { Dog, Cat, Bird };
static constexpr Pets kChosenPet = Pets::Cat;
struct AbstractAnimal {
virtual void Sound() = 0;
};
template <Pets variant = kChosenPet, bool B = (variant == kChosenPet)>
struct Animal : public AbstractAnimal {
void Sound();
};
template <Pets variant>
struct Animal<variant, true> : public AbstractAnimal {
void Sound();
};
template <>
void Animal<Pets::Cat>::Sound() {
printf("Meow!\n");
}
template <>
void Animal<Pets::Dog>::Sound() {
printf("Woof!\n");
}
template <>
void Animal<Pets::Bird>::Sound() {
printf("Peep!\n");
}
May be I don't understand something in your question. But what's wrong with just moving declaration of Sound() to Animal?
#include <stdio.h>
#include <type_traits>
enum class Pets { Dog, Cat, Bird };
template <Pets variant>
class Animal {
void Sound();
};
template<>
void Animal<Pets::Cat>::Sound() { printf("Meow!\n"); }
template<>
void Animal<Pets::Dog>::Sound() { printf("Woof!\n"); }
template<>
void Animal<Pets::Bird>::Sound() { printf("Peep!\n"); }
"SFINAE" means "Substitution Failure Is Not An Error". That starts with "Subsitution", an early part of the template instantiation process. And SFINAE is only Not An Error when there are alternatives for the failed template, e.g. other function overloads.
Now in void Animal<Pets::Bird>::Sound(), there is no Substitution, so SFINAE can't apply. We can't introduce it either - the normal way is via std::enable_if, which can turn a non-template declaration into a template declaration that might or might not be instantiated. But that doesn't work - this specialization cannot be a template declaration.
This case can be simplified:
#ifdef FOO
class Foo { int bar; }
#endif
int Foo::bar() { return 1; } // Also not fixable by SFINAE, for the same reason.
This question already has answers here:
How to create a template function within a class? (C++)
(4 answers)
Closed 7 years ago.
I am looking to start putting in templates in my c++ class code but I have come across a situation I have not experienced before. Basically I have a non-templates class but only 1 function in the class I need to be templated.
class example
{
public:
example();
~example();
<template T> templatefunction(T);
nontemplatefunction(string x);
};
Is this possible? If so, is it a common solution or am I looking at templates completely in error?
As people have noted in the comments, there's no problem doing so.
One aspect to watch out for is where to put the definition of the method templatefunction. For the time being (see the ISO cpp FAQ), you should consider placing it in the header file, which is different than what you'd probably do with the definition of the other methods. Thus you'd have example.hpp:
class example
{
public:
example();
~example();
template<typename T> void templatefunction(T);
void nontemplatefunction(string x);
};
template<typename T> void example::templatefunction(T)
{
}
and then example.cpp:
example::example(){}
void example::nontemplatefunction(string x)
{
}
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 7 years ago.
I have the following class defined in a header A.h :
class A {
private:
template<int i>
void method();
};
is there any way for me to keep the implementation of method in its own A.cpp file , with the usual method implementations ?
I'm asking this because puting the implementation in a A.h would make the interface very hard to read, especially since it's a private function.
It will only ever be instanciated with a limited values of "i" if that matters
You can do the following (as it's widely used practice):
A.hpp
class A {
private:
template<int i>
void method();
};
#include "A.tcc"
A.tcc
template<int i>
void A::method() {
// do something with i
}
Note it's important to name the implementation file with a different extension from .cpp actually, because this will confuse most of the standard build system environments (unless you have complete manual selection of translation unit files).
If you want to have specialized implementations for certain values of i, you can provide them as follows:
// Specialization for 1
template<>
void A::method<1>() {
// do something for specialization with 1
}
template<>
void A::method<2>() {
// do something for specialization with 2
}
After having found answers to many of my questions on stackoverflow, I have now come up against a question of which I can't find the answer and I hope that someone is willing to help me!
My problem is that I want to do an explicit templatization of a function inside a class in C++. My compiler (g++) and a look in the C++ standard (§14.7.3) tells me that this specialization has to be done in the namespace in which the class is declared. I understand that this implies that I cannot put the specialization inside the class, but I don't see the point of this restriction! Does anyone know if there is a good reason for not letting the specializations be made inside the class?
I know that there are workarounds, e.g. to put the function inside a struct, but I want to understand why the language has this design. If there is a good reason for not allowing specialized functions inside the class, I guess I should know it before trying to work around it.
Thanks in advance!
To make my question a little bit more precise: Here is some code from a test example which illustrates what I want to do:
#include <cstdio>
namespace MalinTester {
template <size_t DIMENSIONALITY>
class SpecializationTest {
public:
SpecializationTest() {
privateVariable = 5;
};
virtual ~SpecializationTest() {};
void execute() {
execute<DIMENSIONALITY>();
};
private:
int privateVariable;
template <size_t currentDim>
static void execute() {
printf("This is the general case. Current dim is %d. The private variable is %d.\n", currentDim, privateVariable);
execute<currentDim-1>();
}
template <>
static void execute<0>() {
printf("This is the base case. Current dim is 0.\n");
}
};
This is not possible; g++ says:
SpecializationTest_fcn.h:27: error: explicit specialization in non-namespace scope ‘class MalinTester::SpecializationTest<DIMENSIONALITY>’
SpecializationTest_fcn.h:28: error: template-id ‘execute<0>’ in declaration of primary template
If I put the function execute outside the class, in the name space MalinTester, it will look like this:
#include <cstdio>
namespace MalinTester {
template <size_t DIMENSIONALITY> class SpecializationTest {};
template <size_t currentDim>
void execute() {
printf("This is the general case. Current dim is %d. The private variable is %d.\n", currentDim, privateVariable);
execute<currentDim-1>();
}
template <>
void execute<0>() {
printf("This is the base case. Current dim is 0.\n");
}
template <size_t DIMENSIONALITY>
class SpecializationTest {
public:
SpecializationTest() {};
virtual ~SpecializationTest() {};
void execute() {
MalinTester::execute<DIMENSIONALITY>();
};
private:
int privateVariable = 5;
};
};
};
and I cannot use privatevariable in the templatized versions of execute, as it is private in the class. I really want it private, as I want to have my data encapsulated as far as possible.
Of course I can send privateVariable as an argument to the function, but I think it would be more beautiful to avoid this, and what I really wonder is if there is a good reason for the C++ standard not to allow explicit specialization as in the first code example above.
#Arne Mertz: This is the workaround I have tried, but it doesn't allow using privateVariable either. And most of all, I wonder if it is a good idea to do like this. As I'm not allowed to make specializations of member functions, maybe I shouldn't do specializations of functions encapsulated in structs inside the class either.
#include <cstdio>
namespace MalinTester {
template <size_t DIMENSIONALITY>
class SpecializationTest {
public:
SpecializationTest() {
privateVariable = 5;
};
virtual ~SpecializationTest() {};
void execute() {
Loop<DIMENSIONALITY, 0>::execute();
};
private:
int privateVariable;
template <size_t currentDim, size_t DUMMY>
struct Loop {
static void execute() {
printf("This is the general case. Current dim is %d.\n", currentDim);
Loop<currentDim-1, 0>::execute();
}
};
template <size_t DUMMY>
struct Loop<0, DUMMY> {
static void execute() {
printf("This is the base case. Current dim is 0.\n");
}
};
};
};
Base specialization:
In .h:
template <class T>
class UISelectorSlider : public UISelectorFromRange<T> {
public:
UISelectorSlider();
virtual ~UISelectorSlider();
private:
float width;
float getPositionFromValue(T value);
};
In .cpp under same namespace:
template <>
float UISelectorSlider<MVHue>::getPositionFromValue(MVHue value)
{
return width * (float)value / 360.0;
}
If you want specialized function within specialized class:
Inside class add (.h) (private function):
private:
template <int I>
void foo();
Specialization inside .cpp:
template <>
template <>
void UISelectorSlider<MVHue>::foo<3>()
{
// you can access private fields here
}
UPDATE:
But you cant write something like this:
template <class T>
template <>
void UISelectorSlider<T>::foo<3>()
{
// you can access private fields here
}
You will get: error: enclosing class templates are not explicitly specialized.
It does not matter is this definition inside class or in namespace. The point is that this is not exact partial specialization - this function does not have defined context class (which members you want to call). In other words - when you specialize member you actually try specialize the whole containing class, but not the member itself. And compiler cant do that because class is not yet defined completely. So this is restriction by template design. And if it actually worked - templates would be full equivalent to simple macros.
(And you probably can will solve your task with some macro magic.)
What is the best pratice in regards to defining a template in C++?
template <class T>
class A
{
private:
// stuff
public:
T DoMagic()
{
//method body
}
}
Or:
template <class T>
class A
{
private:
// stuff
public:
T DoMagic();
}
template <class T>
A::T DoMagic()
{
// magic
}
Another way?
I seem to stumble over some controversy regarding this subject.
So; What path to choose?
This is completely a matter of style. That said however:
choose a way and stick to it -- either all inline, or all out, or mixed based on some rule
personally I use a 3 line rule. If the method body in the template is longer than 3 lines I move it outside.
There's no real reason not to include all definitions inline (they are inline from the compilers POV anyway), however, many people argue that keeping them separate is more clean, and allows the class definition to be more readable.
Use an increasing level of separation as the templates you write grow larger and more complex.
Performance will be the same no matter how you separate the definitions from the declarations, so your main concern here should be readability and maintainability.
When writing a simple template used only in one place, declare and define it inline with the declarations right in the CPP file where you're going to use it. There's no reason to force a global recompile if only one block of code needs this template.
file.cpp
template<class Gizmo> bool DoSomethingFancy()
{
// ...
}
For small template utilities used across translation units, define and declare them together in an H file:
utility.h
template<class Gizmo> bool DoSomethingUseful()
{
// ...
}
As your templates become more complex it will become more important to be able to view the declaration separately from the definition. At first, keep everything separate but in the same file:
utility.h
template<class Type> class Useful
{
bool FunctionA();
bool FunctionB();
};
template<class Type> bool Useful<Type>::FunctionA()
{
// ...
}
template<class Type> bool Useful<Type>::FunctionB()
{
// ...
}
But eventually even this will become unwieldly. When it does, separate it in to a header file for the declarations, and an INC file for the definitions. At the end of the header file, #include the INC file:
utility.h :
template<class Type> class MoreUseful
{
bool FunctionA();
bool FunctionB();
};
#include "utility.inc"
utility.inc :
template<class Type> bool MoreUseful<Type>::FunctionA()
{
// ...
}
template<class Type> bool MoreUseful<Type>::FunctionB()
{
// ...
}
This is a religious (style) issue. I prefer to define my functions outside of the template declaration for classes that have more than one method or the few methods are simple.
In either case, my understanding is that the template declaration and the method definitions must be in the same translation unit. This is because the template is more like a stencil, the compiler plugs a given type into the stencil and generates code for the given type.
Whatever you decide, just be consistent.
I usually define all the methods outside but each time I wish C++ had some sort of "template blocks":
template <class T>
struct A
{
T foo();
T bar(T * t);
T baz(T const & t);
};
template <class T> // Made-up syntax
{
T A::foo()
{
//...
}
T A::bar(T * t)
{
//...
}
T A::baz(T const & t)
{
//...
}
}
If the functions are non-trivial (i.e. more than one or two lines), consider defining them separately. This makes the interface of the class much easier to navigate, read and understand for the users of your class, who most likely shouldn't have to look at the actual implementation of each method.
For a one-off instance like your example, it makes little difference.
What happens when there are lots of templates with lots of variations? It then helps to put similar types of apples together, and similar types of oranges together away from them. Of course, this must all be done as intuitively as practical. That is greatly affected by the culture of programmers working with the code.