I have a bunch of related indicies in a kind of templated hierarchy, looking something like
template <int level>
struct index{
index<level - 1> w;
int x, y;
};
template <> struct index<0> { int x, y; };
template <int level>
struct data;
and a class that's supposed to generate and cache objects indexed by them. I want to use pimpl for this class, and I'm wondering if there's a way to forward the function calls to the implementation class using templates. Something like
class Cache{
template <int level>
shared_ptr<data<level>> get_data(const index<level> & index);
};
In short, no (if I understand your question correctly).
The problem is that at the point of implementation of your forwarder, you need the full definition (and not just a declaration) of your implementation class. If you want to use template member functions for this purpose you need to define them in every compilation unit that uses them, i.e. typically in the same header where you declare them. This means that the implementation class needs to be defined in the same header where you declare your interface class (which would defeat the purpose of pimpling the class in the first place).
(In case your compiler supports the export keyword, you can define template methods separately, so in this case it would work. In practice, Comeau is the only compiler I know that supports export, and it has been removed from C++11 completely).
Compare How can I avoid linker errors with my template functions? in the C++-FAQ-lite.
Related
Usually, one declares a member function in a header file and uses a source file to implement it. My understanding of the reason is that the function implementation will reside in only one translation unit and will be just linked to other units (no duplicate code), and it also allows separation of the interface and implementation, and removes the need to forward declare functions that depend on each other.
However, member functions in a template depend on the template arguments, which couldn't be known if the implementation was placed in a source file. However, it is still possible to define such functions outside the class, but the major argument for it doesn't apply anymore.
So, which is better?
template <class T>
class A
{
T m()
{
return T();
}
};
or
template <class T>
class A
{
T m();
};
template <class T>
T A::m()
{
return T();
}
These two pieces of code would be equivalent if it was inline T A::m(), but is there any difference without it? What if the function is virtual? Is it just a matter of coding style, or does it have different semantics? If the function is large enough, will it prevent duplicate code, or is the compiler smart enough not to inline it if it won't bring any benefits?
These two pieces of code would be equivalent if it was inline T A::m(), but is there any difference without it?
Not for templates, the member functions are implicitly inline, for both inside and outside the class definitions.
What if the function is virtual?
Makes no difference.
Is it just a matter of coding style, or does it have different semantics?
Mostly stylistic. However, it affects how name lookup works. So if we were to modify the class definition a bit
template <class T>
class A
{
using foo = T;
foo m();
};
We would not be able to define the member outside as
template <class T>
foo A<T>::m()
{
return T();
}
Since the lookup for foo doesn't happen inside the class definition until after the qualification A<T>::. We'd need to either fully qualify foo itself, like so typename A<T>::foo. Or perhaps use a trailing return type.
If the function is large enough, will it prevent duplicate code, or is the compiler smart enough not to inline it if it won't bring any benefits?
Neither style should have either an adverse of positive effect on it. Both are subject to quality of implementation issues. But of course, different implementations may have different qualities.
Is there a good rule when to use a class template instead of using member templates?
As I understand it, your are forced to use a class template if your class contains member variable templates but otherwise you are free of choice since this:
template<typename T>
class Foo
{
public:
void someMethod(T x);
};
behaves like this:
class Foo
{
public:
template<typename T>
void someMethod(T x);
};
Is my claim wrong? Or is there any rule of thumb when to use what?
The two are not at all the same. With the first:
Foo<int> f;
f.someMethod('a');
the called function is someMethod(int).
With the second:
Foo f;
f.someMethod('a');
the called function is someMethod(char).
You can choose to make your class a template, rather than having member function templates, for several reasons. Say you have a template parameter T.
Like you said, if you have a member variable of type T, your class needs to be a template.
If you have a function returning T and not accepting T, and you don't want to manually specify the type in each invocation, your class needs to be a template.
If you need a virtual function that depends on T, your class needs to be a template.
If you need a different class layout (i.e. member variables) per instantiation of T, your class needs to be a template.
If you need to make sure that your functions all operate on a single type rather than generate different versions of them arbitrarily, your class needs to be a template.
The best rule of thumb would be to use the simplest thing that makes sense. In general, member function templates tend to be more rareāand virtually non-existent for the use case you're talking about. Maybe that's no coincidence.
We have following class definition
template<typename T>
class Klass {...}
and we also have below two instantiations
Klass<int> i;
Klass<double> d;
how many copies of Klass' methods are generated by the C++ compiler?
Can somebody explain it? Thanks!
Klass isn't a type, so it doesn't make sense to talk of Klass's methods. Kalss<int> is a type with it's own methods, and so is Klass<double>. In your example there would be one set of methods for each type.
Edit in real life, it isn't as simple as that. The question of the actual existence of the methods also depends on other factors, see #KerrekSB's answer to this question.
Each template instance is an entirely separate, distinct and independent type of its own. However, the code for class template member functions is only generated if the member function is actually used for a given template instantiation (unless you instantiate the template explicitly for some set of parameters). Among other things, this means that if some class template member function's body doesn't actually make sense for a given template parameter, then you can still use the overall template as long as you don't invoke that member function, since the code for the member function will never get compiled.
Also bear in mind that templates can be specialized:
template <typename T> struct Foo {
int bar;
void chi();
};
template <> struct Foo<int> {
double bar(bool, char) const;
typedef std::vector<bool> chi;
bool y;
};
As you can see, there's a lot you cannot just tell from a template itself until you see which actual instantiations you'll be talking about.
I'm writing a template class that uses a std::multimap as a member, and getting compile errors.
LocTree.h:
#pragma once
#include <map>
template <class Loc, class T>
class LocTree
{
public :
typedef std::multimap<typename Loc, typename T> TreeType;
LocTree( void );
~LocTree( void ) { };
private :
TreeType db;
};
LocTree.cpp:
#include "StdAfx.h"
#include "LocTree.h"
LocTree< class Loc, class T>::LocTree()
{
}
The compile error (from VC2005) :
Error 1 error C2079: 'std::pair<_Ty1,_Ty2>::first' uses undefined class 'Loc' c:\program files (x86)\microsoft visual studio 8\vc\include\utility 53
Error 2 error C2079: 'std::pair<_Ty1,_Ty2>::second' uses undefined class 'T' c:\program files (x86)\microsoft visual studio 8\vc\include\utility 54
I know I could put the function definitions in the .h but I'm hoping to keep them separate, if it's legal to do so. How do I fix this (probably newbie) problem?
Your constructor definition should be:
template<class Loc, class T>
LocTree<Loc,T>::LocTree()
{
}
Also, hoping to keep them separate... - don't - you're wasting your time. The only way to keep them separate is to have a definition in a different header which you also include. So, technically, they are separate, but the implementation is still visible.
Two points. The first is: what is:
typedef std::multimap<typename Loc, typename T> TreeType;
supposed to mean? I don't see what the typename are doing in there; I
think you just want:
typedef std::multimap<Loc, T> TreeType;
Second, when defining a member function of a class template outside of the
class, the syntax is:
template <typename Loc, typename T>
LocTree<Loc, T>::LocTree()
{
}
In other words, you have to repeat the template<...> clause. (Whether
you use typename or class in the <...> is indifferent. Since it
doesn't have to be a class, Most people I know prefer typename, since
this corresponds closer to what is meant.)
As for keeping the implementation separate: templates in C++ are
somewhat broken in this respect. You can't avoid the compiler
dependency. You still do want to keep the implementation separate from
the definition, however. The usual technique is to put the template
implementation in a separate file (.tcc, for example), and include
this from the header.
Keeping the implementation of a template separate is not a trivial thing to do.
In general it cannot be done. That is, it cannot be done where the templated parameters may be "anything".
For a specific limited subset of templated parameters it is possible to do, for example if you have a template like:
template< bool B > class Foo;
You can then specify:
extern template class Foo<true>;
extern template class Foo<false>;
and this is called "instantiating" the templates, and specifying to the compiler that there are implementations for values true and false, implemented elsewhere.
This can also be done where the templated parameters are types and are limited to a specific subset.
Within the compilation unit you then define the template implementations and then instantiate the templates once again using the same as above but without the word "extern".
I have done this in production code in a case where you are creating a member function to set a parameter value for a database stored-procedure call where only a very limited subset of parameter types are permitted. If your types are a very limited subset then go ahead and do the same if this helps decouple the code and hide a lot of implementation detail (in the case where the implementation is then done in a database, it is well worth doing).
There is an "in-between" ground where you provide the implementation in another header, often I have seen _i.h or similar for this convention and then you instantiate the templates in ones, including this header only when necessary. Thus if you create a class Foo then in the header use the "extern" declaration for my foo class in Foo.h and in Foo.cpp, #include the _i.h file for the implementation and the instantiation.
As for the syntax, in the template implementation file use:
template<class Loc, class T>
LocTree<Loc,T>::method(...)
{
...
}
Suppose I've written class template declaration somewhere in collector.h:
template <class T, int maxElements>
class collector {
T elements[maxElements];
int activeCount;
public:
collector();
void process();
void draw();
};
and implementing its three methods in collector.cpp:
template <class T, int maxElements>
collector<T, maxElements>::collector(){
//code here
}
template <class T, int maxElements>
void collector<T, maxElements>::process(){
//code here
}
template <class T, int maxElements>
void collector<T, maxElements>::draw(){
//code here
}
Is there any way of not writing template <class T, int maxElements> and <T, maxElements>
for every function's implementation? Something like that:
template <class T, int maxElements>{
collector<T, maxElements>::collector(){
//code here
}
void collector<T, maxElements>::process(){
//code here
}
void collector<T, maxElements>::draw(){
//code here
}
}
Put the code inside the class definition in the header file.
[You'll probably wind up doing this anyway as soon as you try to build code that uses this class template. See here for background esp. the neglected answer from #Pavel Minaev.]
Nope, you gotta write the template header every time.
Typically, people implement template classes directly inline. They have to have their full source exposed to be used (unless you explicitly instantiate the lot, anyway) so there's little point doing otherwise.
Is there any way of not writing template and for every function's implementation?
No, short of defining template members inline in the class template's definition, there is no way to do that.
The direct answer to your question has been answered by many above.
To know more on whats the best practice, refer to chapter 6 of C++ Templates - The complete guide book. It talks about which is the best place to declare and/or define template class, functions, member functions: in a .h/hpp or .cpp files.
There's always copy & paste!
Unless you have a smart C++ template-aware linker closely coupled to your compiler, you'll have to put the code in-line in the header in any case and the problem goes away. You'll want to do that in any case if the code needs to be portable.
If you really must then there is the somewhat perverse pre-processor macro solution:
#define COLLECTOR_TEMPLATE template <class T, int maxElements>
Explicitly instantiate for all the types you expect to need in the .cpp file so the compiler can generate the code a priori the linker will match the references templkates to the pre-instantiated definitions (see http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13. You will however not be able to instantiate the template for new types.
For separate compilation of templates to work for arbitrarily instantiated classes, the compiler would have to embed the template source in the object file, then when the linker requires a particular instantiation to resolve a reference, it must then extract that source and pass it back to the compiler to generate the instantiated object code, which is then passed back to the linker. This requires the compiler and linker to work hand-in-glove, and for an object file format that supports template source embedding.
Most tool-chains do not support that, so you must either use in-line definition in the header, restrict use of the template to the same source file in which it is defined, or #include the .cpp containing the definition; all three of these are effectively the same thing - making the complete template definition visible to the compiler in a single compilation unit, but the first is the most conventional and flexible solution.