Sign in to follow this  

C++ Template Questions ...

This topic is 3791 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Today I picked up The C++ Standard Library: A Tutorial and Reference . I've never bothered to use templates before, only read about them, so I am more than rusty. 1) When declaring template functions what is the difference between: template <typename T> and template <class T> 2) The book also goes on to use the "typename" keyword in a manner that I don't quite understand. An example in the book is is: template<Class T> class MyClass{ typename T::SubType * ptr; } Even with the explanation in the book, I have no clue how typename is being used here :( 3) Also the book says that template functions have to be defined as inline functions in header files. Does that mean that the entire STL is defined entirely in header files? Is it possible to ever separate the declaration and definition of template classes/functions?

Share this post


Link to post
Share on other sites
For (1), there is no difference in that context between "typename" and "class."

For (2), it's not entirely accurate that they need to be defined in headers - they just need to be defined such that they are in scope when they are going to be used. In practice, this means you put them in a header file, but if you only need a template for a single translation unit (a rare case), you can put the whole thing in the source file.

Yes, the entire SC++L is in headers. The "export" keyword is supposed to help in splitting templates, but almost no compilers support it, because it's very hard to implement and it doesn't gain you much.

In practice, most people separate template class definition and function defintion by having the bottom of the template.h have an #include "template.inl" directive -- using a filename with an extension that is not normally picked up as "compilable" by the toolchain, as ".cpp" files are.

Share this post


Link to post
Share on other sites
1) You can use class and typename interchangeably. There are synonymous.
2) When you are using a nested type inside a template parameter (in this case, the template parameter is T and you are using a nested type of T), you must prefix it with typename. This helps the compiler since it doesn't know until the template is "instantiated" (used with a concrete type instead of the placeholder T) whether SubType is really a type or not.
3) Yep. STL is all in header files. You can separate the declaration from the definition, but it must all be in the same header file. The only case where implementation can go into a .cpp file is a template specialization.


template<class T> class Foo
{

void MyFunc ();
};

template<class T> void Foo<T>::MyFunc ()
{
}

Share this post


Link to post
Share on other sites
Quote:
Original post by strtok
2) When you are using a nested type inside a template parameter (in this case, the template parameter is T and you are using a nested type of T), you must prefix it with typename. This helps the compiler since it doesn't know until the template is "instantiated" (used with a concrete type instead of the placeholder T) whether SubType is really a type or not.


So the type that will be Represented by T has within it an item that is either
a) typedef'd to type SubType
b) declaration of class SubType;

Could SubType also be yet another template parameter?

Also the book mentions "Nontype Template Paramers". Could someone show me some example syntax where a template doesn't contain type information?

eg: bitset<32> flags32; // bitset with 32 bits

[edit]

Also why are "Nontype Template Paramers" useful? It seems to me that they can be avoided.

Also sorry to jpetrie , I edited my post just as you replied :)

Share this post


Link to post
Share on other sites
A hopefully clearer example for (2).


struct Foo {
int SubType;
};

struct Bar {
typedef int SubType;
SubType quux;
};

struct Baz {
struct SubType {};
};

template<Class T>
class MyClass {
typename T::SubType * ptr;
};

MyClass<Foo> foo; // The compiler complains when the template is instantiated,
// because Foo::SubType is a *data member*, not a type name.

MyClass<Bar> bar; // ok

MyClass<Baz> baz; // also ok

MyClass<int> i; // obviously not ok ;)



Without the 'typename' keyword qualifying 'T::SubType', the compiler doesn't know that that's actually a type name, because it could be different *kinds of things* in different classes.

The compiler requires 'typename' in this context so that it can give you more meaningful error messages, basically.

Quote:
Original post by fpsgamer
Also the book mentions "Nontype Template Paramers". Could someone show me some example syntax where a template doesn't contain type information?

eg: bitset<32> flags32; // bitset with 32 bits


You already gave yourself an example; what's the problem? :)

Quote:

Also why are "Nontype Template Paramers" useful? It seems to me that they can be avoided.


Here's a simple, practical use:


template <typename T, size_t n>
class Array {
T storage[n];
public:
T& operator[](size_t i) { return storage[i]; }
const T& operator[](size_t i) const { return storage[i]; }
};


This is a stripped down implementation of boost::array. The intent is to make it easier to pass arrays to functions (and return them from functions): by wrapping the array in an object, you avoid pointer decay. The template allows you to make it work with any size of array.

With substantially more work, you could define, say, an n-bit unsigned integral type, where values range from 0 up to 2^n - 1, using some contiguous bytes for storage and overloading mathematical operators to make it behave as if the machine actually supported integers of that size. (You could even define them to avoid overflow problems: e.g. template <size_t bits> Integer<bits + 1> operator+(const Integer<bits>&, const Integer<bits>&); since in general you need one more bit to hold the result of an addition.)

Share this post


Link to post
Share on other sites
The only difference between class and typename is that class can be used to provide class template template arguments to a template, whereas typename can't. Consider:

template<template <class T> class C> // must be "class"
std::string to_string(const C<char> & c)
{
return std::string(c.begin(),c.end());
}

Share this post


Link to post
Share on other sites

This topic is 3791 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this