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
}
Related
I have a set of templates where each base template has some large specializations and many of the other methods are mainly casts around types and constructors and operator=(). I made templates to factor out all those little methods as inlines and put the fat ones in the CPP files for a shared library. In windows it compiles and links fine into a DLL. It all does what I want on MSC but on GCC with the specialization code in the C++ file many of the specializations occur "after instantiation" with GCC.
Structurally the code is like the below. (the real case is more messy) I'm not sure what I need to do as the template method declarations that call their superclass methods (from other templates) are where the method code is "instantiated" for their superclass templates. What I need to do is somehow defer the instantiation until after the header declarations to happen in the .cpp file where the specialization's method bodies for the library are compiled.
// header file .h
template<class SubClassT, class CharT>
class XBaseT
: public YBaseT<char_object<CharT>>
{
typedef XBaseT<XObject,CharT> super;
public:
typedef char_object<CharT> ObjT; // seen by subclasses
inline XBaseT() {}
inline XBaseT(ObjT &p); // note no body, then intention is to have this specialization in library, not header.
...
};
template<>
class XClass<XObject>
: public XBaseT<XObject,char>
{
typedef XBaseT<XObject,char> super;
public:
inline XClass() {}
inline XClass(ObjT &p) : super(p) {}
...
};
template<>
class XObject
: public ContainerT<XObject>
{
typedef ContainerT<XObject> super;
public:
inline XObject() {}
static ContainerT<XObject> *static create(InitStruct &is);
...
};
// specializations in cpp file
tenplate<>
ContainerT<XObject> *
create(InitStruct &is) {
// big code here needs to be in CPP file for library
}
// specialization for <XObject,char> happens "after instantiation" even thoght the method in it's template class is declared with no body.
template<>
XBaseT<XObject, char>::XBaseT(ObjT *p) {
p_ = XObject::create(p);
}
The specialization just above in the.cpp file barfs on GCC as it is "after instantiation",
The instantiation in GCC happens when the "inline XClass(ObjT *p) : super(p) {}" constructor in XClass is declared. And that is so tiny I would like it to be inline as it should optimize out to nothing. On MSC the code is not instantiated until explicitly done so in the .cpp file. and the with MSC the linker seems to sort out what is needed and the compiler warns of missing methods declared but NOT instantiated there. In a declaration of
template class XBaseT;
template class ContainerT;
template class XClass;
The issues is some of the methods specialized for these templates are dependent on more than one of the templates and the specializations need to happen after the declarations.
How do I using "typename" or other template features get this for compile and link under CCC as opposed to windows MSC ?
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 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.
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 9 years ago.
Please read this first:
Storing C++ template function definitions in a .CPP file
This is what I am attemptng here.
I used the first method from this site to define a template class in a cpp file:
http://www.codeproject.com/Articles/48575/How-to-define-a-template-class-in-a-h-file-and-imp
It looks like this:
b.h :
#ifndef B_H_
#define B_H_
class B
{
public:
B();
};
#endif
a.h :
#ifndef A_H_
#define A_H_
template<class T>
class A
{
public:
A();
int get();
private:
int val;
};
#endif
a.cpp
#include "a.h"
template <class T>
A<T>::A()
{
}
template <class T>
int A<T>::get()
{
return 42;
}
// No need to call this TemporaryFunction() function,
// it's just to avoid link error.
void TemporaryFunction ()
{
TestTemp<B> TempObj;
}
main.cpp
#include "a.h"
int main(int argc, char** argv){
A<B> ab;
ab.get();
}
I have to change get to virtual or I get:
undefined reference to `A::get()'
I don't understand this.
This is just a sample of the real code (that is too large). If it does not reproduce, I will provide more details tomorrow.
gcc version 4.8.1 (Ubuntu/Linaro 4.8.1-10ubuntu9)
Template members are either explicitly instantiated or instantiated on demand. You are not explicitly instantiating the template, but rather causing the implicit instantiation of the type and the constructor by means of the local variable. Since you don't use A<B>::get() that function will not be instantiated by the compiler.
If the function is marked as virtual, then it is odr-used just by means of instantiating the object (hint: the address of each virtual function, or a similar piece of information, needs to be stored in the vtable).
That being said, and without reading the article in question, this approach is wrong. You don't need to create the function and cause the instantiation of each member function, but rather use explicit instantiation of the template.
template class A<B>; // Explicit instantiation
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.