Sign in to follow this  
TEUTON

class or typename

Recommended Posts

TEUTON    100
I always use keyword class in templates but I know we can also use typename. I don't think language provided reduntant things. Is there any special case where I should use typename.?

Share this post


Link to post
Share on other sites
Drew_Benton    1861
Quote:
Original post by TEUTON
I always use keyword class in templates but I know we can also use typename. I don't think language provided reduntant things. Is there any special case where I should use typename.?


Yes, when you need to compile typedef'd templates. For example:
typedef typename Mgr::iterator MgrItr;
typedef typename Mgr::const_iterator ConstMgrItr;

Is valid code and works correctly, but if you were to use
typedef class Mgr::iterator MgrItr;
typedef class Mgr::const_iterator ConstMgrItr;

Then it would not compile.

Here's an example if you want it:

// Templated Manager Class
// By: Drew Benton - drew.benton@gmail.com
// License: Allegro Giftware License
// License URL: http://www.talula.demon.co.uk/allegro/license.html

#pragma once

#include <map>
#include <algorithm>

using std::map;
using std::make_pair;

template <typename keyType, typename dataType>
class Manager
{
public:
// Use a typedef for the map, so we can jsut type 'Mgr' rather than 'map<keyType, dataType>'
// Also makes changing the map easier, such as if you wanted to use a hash-map or multi-map
typedef map<keyType, dataType> Mgr;

// This is the tricky part, if you forget that typename, lots of headaches,
// it's even worse when you switch the two in DevCpp!
// The reason we use this is so when we need an iterator, we can just use 'MgrItr' or 'ConstMgrItr'
// as the type rather than 'map<keyType, dataType>::iterator' each time, cleans up code!
typedef typename Mgr::iterator MgrItr;
typedef typename Mgr::const_iterator ConstMgrItr;

private:
// Map of the keys and data
Mgr data;

// The form that the function pointer will fit for the process function
typedef void(*ProcessFuncPtr)(dataType);

// The function pointer for the Process function, if you do not need this functionality,
// simply do not call the SetProcess function
ProcessFuncPtr Process;

public:
// Default ctor
Manager() : Process(0) { }

// Default dtor
~Manager() { }

// This is just one form of add you can have, returns true on success
// and false of failure. This is a 'key' search, you search based on the key
void Add(keyType key, dataType dataValue)
{
// First see if the entry already exists in the map
MgrItr itr = data.find(key);

// If the key already exists
if(itr != data.end())
{
// Only one key per this type of map
// *you can use a multimap if you wanted more than one set of data per key*
throw("Key already exists in the map");
}

// Isn't the Standard C++ Lib great! make_pair will automatically create what you need
// based on the passed parameters. Otherwise you'd have to do "pair<K, dataType>(key, dataValue)"
data.insert(make_pair(key, dataValue));
}

// This is the improved remove function that will Process the data by passing it to the
// registered process function if doProcess is true. Otherwise it removes the key from the map
void Remove(keyType key, const bool &doProcess)
{
// First see if the entry already exists in the map
MgrItr itr = data.find(key);

// If the key does not exists
if(itr == data.end())
{
// The key wasn't in the map
throw("Key does not exist in the map");
}

// If we want to clean up the data
if(doProcess)
{
// Does the function pointer exist?
if(Process)
{
// Send the data to be deleted
Process(itr->second);
}
else
{
// If we told it to process, yet have no registered function
throw("No process function registered!");
}
}

// Simply remove the data from the map
data.erase(itr);
}

// Returns the data with the specific key
dataType Get(keyType key)
{
// First see if the entry key exists in the map
MgrItr itr = data.find(key);

// If the key does not exists
if(itr == data.end())
{
// The key wasn't in the map, so handle that here
throw("Key does not exist in map");
}

// Success
return itr->second;
}

// Returns the reference of the data with the specific key so it can be changed
dataType &GetRef(keyType key)
{
// First see if the entry already exists in the map
MgrItr itr = data.find(key);

// If the key does not exists
if(itr == data.end())
{
// The key wasn't in the map, so handle that here
throw("Key does not exist in map");
}

// Success
return itr->second;
}

#ifdef EXPOSE_DATA_PTRS
// Returns the data with the specific key
dataType* GetPtr(keyType key)
{
// First see if the entry key exists in the map
MgrItr itr = data.find(key);

// If the key does not exists
if(itr == data.end())
{
// The key wasn't in the map, so handle that here
throw("Key does not exist in map");
}

// Success
return (&itr->second);
}
#endif

// By default this is not exposed
#ifdef EXPOSE_DATA_ITRS
// Returns the iterator with the specific key
MgrItr GetItr(keyType key)
{
// First see if the entry already exists in the map
MgrItr itr = data.find(key);

// If the key does not exists
if(itr == data.end())
{
// The key wasn't in the map, so handle that here
throw("Key does not exist in map");
}

// Success
return itr;
}

// Returns the begin iterator of the data
ConstMgrItr GetDataBegin()
{
return data.begin();
}

// Returns the end iterator of the data
ConstMgrItr GetDataEnd()
{
return data.end();
}
#endif

// Set's the entire data to be replaced, if doProcess, the old data is processed first
void Replace(keyType key, dataType newData, const bool &doProcess)
{
// First see if the entry already exists in the map
MgrItr itr = data.find(key);

// If the key does not exists
if(itr == data.end())
{
// The key wasn't in the map, so handle that here
throw("Key does not exist in map");
}

// If we should process the data before we set
if(doProcess)
{
// Does the function pointer exist?
if(Process)
{
// Send the data to be processed
Process(itr->second);
}
else
{
// If we told it to Process, yet have no registered function
throw("No process function registered!");
}
}

// Success
itr->second = newData;
}

// Return the number of tracked elements
size_t GetSize() const
{
return data.size();
}

// Register our data processing function pointer
void SetProcessFunctionPtr(ProcessFuncPtr processFunction)
{
Process = processFunction;
}

// Clean up the manager! This is made a separate function in case
// at some time you want to 'start fresh' again.
void Clear(const bool &doProcess)
{
// Get the first element in the map
MgrItr itr = data.begin();

// Loop though all of the data
while(itr != data.end())
{
// If we want to process the data
if(doProcess)
{
// If there's a function registered
if(Process)
{
// Pass the data to the function to be processed
Process(itr->second);
}
else
{
// If we told it to process, yet have no registered function
throw("No process function registered!");
}
}

// Remove from the manager
data.erase(itr);

// Set the itr to the beginning again
itr = data.begin();
}
}
};

typedef void (*func)(int);

void main()
{
Manager<int, func> var;
}




Other than that, they are pretty much the same I'd suppose.

Share this post


Link to post
Share on other sites
Bregma    9199
Quote:
Original post by TEUTON
I always use keyword class in templates but I know we can also use typename. I don't think language provided reduntant things. Is there any special case where I should use typename.?


In the case of template parameters, the two are synonyms. There is no difference. None. It's like the class/struct synonym, but without the public/private differentiator.

The reason for the synonyms is historical (C++ has always been big on backwards compatibility with millions of lines of existing code).

COnventional wizdom is to use 'typename' most of the time, but 'class' when you're expecting a non-POD class for a particular template.

Don't confise the dependent-name specifier 'typename' with the template parameter 'typename'. That would be like confising the class declarator 'class' with the template parameter 'class'.

Share this post


Link to post
Share on other sites

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