Templated Templates?

Hi,

I'm wanting to write some templates that use templates. I can do this by leaving a complex object as a generic type, but what if I want to ensure that some of the types within the templates are matching? For example, suppose I want to write a template function that takes a pair of long and double and inserts it into a map, a multimap, a set, a multiset, a deque, or whatever I pass in as a container type? If so, I want to make sure the container holds the type I'm adding. For simplicity, let's start by sticking to map and multimap.

Here is what works but doesn't satisfy me:
1
2
3
 
template< class POS_DATA,class SCORE_DATA, class MAPTYPE > 
void insertNewData(pair< POS_DATA,SCORE_DATA>&newData, MAPTYPE&mappedData);


Here is what I wanted:
1
2
3
4
 
template< class POS_DATA,class SCORE_DATA, template < POS_DATA,SCORE_DATA> class MAPTYPE > 
void insertNewData(pair< POS_DATA,SCORE_DATA>&newData, MAPTYPE< POS_DATA,SCORE_DATA>&mappedData);
       

That leads to this error:
error: template argument for non-type template parameter must be an expression

Then I tried:
1
2
3
template< class POS_DATA,class SCORE_DATA, template <class POS_DATA,class SCORE_DATA> class MAPTYPE > 
void insertNewData(pair< POS_DATA,SCORE_DATA>&newData, MAPTYPE< POS_DATA,SCORE_DATA>&mappedData);
       

And that leads to this error:
error: declaration of 'POS_DATA' shadows template parameter


I tried changing the names of the repeating types too, but then it complains that they aren't the same type when I try to assign one of the first type to one of the equivalent second types. Any suggestions?

Last edited on
std::map, std::unordered_map, etc. have the typedefs key_type and mapped_type that you can use.
1
2
template<class MAPTYPE > 
void insertNewData(pair<typename MAPTYPE::key_type, typename MAPTYPE::mapped_type>& newData, MAPTYPE& mappedData);


But this will only work for maps.

All containers have typedef value_type and std::pair have typedefs first_type and second_type that you can use. I think something like this should work:
1
2
template<class MAPTYPE > 
void insertNewData(pair<typename MAPTYPE::value_type::first_type, typename MAPTYPE::value_type::second_type>& newData, MAPTYPE& mappedData);
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <string>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <deque>

template< typename CONTAINER >
void insert_data( typename CONTAINER::value_type&& value, CONTAINER& container )
//{ container.insert( container.end(), value ) ; } // this is a push_back for sequence containers
{ container.insert( container.end(), std::forward< typename CONTAINER::value_type >(value) ) ; } // *** EDIT

int main()
{
    std::set<int> a ; insert_data( 100, a ) ; insert_data( 100, a ) ;
    std::unordered_multiset <std::string> b ; insert_data( "hello", b ) ; insert_data( "hello", b ) ;
    std::unordered_map<int,std::string> c ; insert_data( { 100, "hello" }, c ) ;
    std::multimap<std::string,int> d ; insert_data( { "hello", 100 }, d ) ; insert_data( { "hello", 200 }, d ) ;
    std::deque<std::string> e ; insert_data( "hello", e ) ; insert_data( "hello again", e ) ;
}
Last edited on
Topic archived. No new replies allowed.