Show Lecture.TemplateImplementation as a slide show.
CS253 Template Implementation
Pick One
- There are two fundamentally different ways to implement a
template class:
- The
*.h
file contains inline method bodies (code), all in the
class declaration itself. Method bodies are inside
class Foo { ... };
.
- The
*.h
file contains the class declaration, with no method
bodies. After that, comes each method body.
- The first technique is shorter, but mixes interface & implementation,
and so is hard to read.
- Neither technique involves a
*.cc
file. Though the C++ standard
allows for this, current compilers can’t handle it.
- No
*.h
file should contain a using namespace declaration.
Inline
#include <iostream>
template<typename T>
class Foo {
T data;
public:
Foo(const T &value) : data(value) { }
T get() const { return data; }
};
template<typename T>
std::ostream & operator<<(std::ostream &os, const Foo<T> &f) {
return os << f.get();
}
- The ctor and
get()
method bodies are inside the class.
operator<<
is outside of the class, because it’s not a method.
Not Inline
#include <iostream>
template<typename T>
class Bar {
T data;
public:
Bar(const T &);
T get() const;
};
template<typename T>
Bar<T>::Bar(const T &value) : data(value) {
}
template<typename T>
T Bar<T>::get() const {
return data;
}
template<typename T>
std::ostream & operator<<(std::ostream &os,
const Bar<T> &b) {
return os << b.get();
}
- The class declaration itself contains no method bodies.
- Each body is preceded by
template<typename T>
,
because each is defining a family of functions.
- Each method needs
Bar<T>::
before its name to indicate that it’s a
method and not a free function.
Example
from ~cs253/Example/Templates
:
$ cp ~cs253/Example/Templates/* .
$ ls
Bar.h Foo.h index.php Makefile test.cc
$ cat test.cc
#include "Foo.h"
#include "Bar.h"
#include <iostream>
int main() {
Foo<short> f(12);
Bar<long> b(34);
std::cout << f << ' ' << f.get() << ' ' << sizeof(f) << '\n'
<< b << ' ' << b.get() << ' ' << sizeof(b) << '\n';
}
$ make && ./test
g++ -Wall -Wextra -Wpedantic -Werror -Wfatal-errors -o test test.cc
12 12 2
34 34 8
Templated Methods
class Show {
public:
void m(double d) const { cout << "Double: " << d << '\n'; }
template <typename T>
void m(T v) const { cout << "Value: " << v << "\n"; }
};
int main() {
Show s;
s.m("hello");
s.m(1.2);
s.m(&s);
}
Value: hello
Double: 1.2
Value: 0x7ffe4a78a2ff
If all you need is a templated method, then there’s no need to
templatize the entire class, just the method that needs arguments of
varying types.
If the number of different types is small, then avoid templates;
write several methods with different argument types.