Class template specialization with template parameter

Discussion in 'C++' started by flopbucket, May 14, 2008.

  1. flopbucket

    flopbucket Guest

    Hi,

    I want to provide a specialization of a class for any type T that is a
    std::map.

    template<typename T>
    class Foo
    {
    // ...
    };

    template<typename K, typename V>
    class Foo<std::map<K, V> >
    {
    // ...
    };

    It seems to work - is this the correct way to do this?

    Foo<int> uses the normal template, but Foo<std::map<T1, T2> > for any
    types of T1 and T2 uses the specifalization?

    Thanks
    flopbucket, May 14, 2008
    #1
    1. Advertising

  2. flopbucket

    flopbucket Guest

    Hi,

    First, thanks for the reply.


    > > Foo<int> uses the normal template, but Foo<std::map<T1, T2> > for any
    > > types of T1 and T2 uses the specifalization?

    >
    > Not sure what you're asking here.


    What I was trying to say was that if I declare:

    Foo<int> myFoo();

    The instantiation will be for the normal/not-specialized template.

    But if I declare:

    Foo<std::map<int, std::string> > myFoo2();

    it will use the specialization... and that regardless of the types
    used for std::map (in this case, int and std::string), any
    "Foo<std::map<typeA, typeB> > myFooExample()" will always
    instantiate the specialization.

    Thanks
    flopbucket, May 14, 2008
    #2
    1. Advertising

  3. flopbucket

    Greg Herlihy Guest

    On May 14, 12:51 pm, flopbucket <> wrote:
    > Hi,
    >
    > First, thanks for the reply.
    >
    > > > Foo<int> uses the normal template, but Foo<std::map<T1, T2> > for any
    > > > types of T1 and T2 uses the specifalization?

    >
    > > Not sure what you're asking here.

    >
    > What I was trying to say was that if I declare:
    >
    > Foo<int> myFoo();


    I believe that you mean to declare an object (and not a function):

    Foo<int> myFoo;

    > The instantiation will be for the normal/not-specialized template.


    Yes.

    > But if I declare:
    >
    > Foo<std::map<int, std::string> > myFoo2();


    Again, I believe that you want:

    Foo<std::map<int, std::string> > myFoo2;

    > it will use the specialization... and that regardless of the types
    > used for std::map (in this case, int and std::string), any
    > "Foo<std::map<typeA, typeB> >  myFooExample()"  will always
    > instantiate the specialization.


    The answer depends on how many template parameters "std::map"
    requires. The usual number is two - the two specified by the C++
    Standard. An implementation however is allowed to require additional
    temmplate type parameters for a std::map. So, assuming that std::map
    requires only two type parameters, then the answer is "yes".

    Greg
    Greg Herlihy, May 14, 2008
    #3
  4. flopbucket

    flopbucket Guest

    >
    > Yes. Of course, 'myFoo' in that case is a function, but the template
    > is still instantiated, I believe.


    Right, my mistake. Should bee 'Foo<int> myFoo;'

    >
    > Yes. Or do you still have a doubt about that?


    No, thanks, just wanted to run it by some experts - I've done
    specializations before but this one was a bit more "advanced" then
    normal basic types, since std::map<> itself is a template. I just
    wasn't sure of myself.

    Thanks for the clarifications.
    flopbucket, May 14, 2008
    #4
  5. flopbucket

    James Kanze Guest

    On May 14, 10:20 pm, Greg Herlihy <> wrote:
    > On May 14, 12:51 pm, flopbucket <> wrote:
    > > > > Foo<int> uses the normal template, but Foo<std::map<T1,
    > > > > T2> > for any types of T1 and T2 uses the
    > > > > specifalization?


    > > > Not sure what you're asking here.


    > > What I was trying to say was that if I declare:


    > > Foo<int> myFoo();


    > I believe that you mean to declare an object (and not a function):


    > Foo<int> myFoo;


    > > The instantiation will be for the normal/not-specialized template.


    > Yes.


    > > But if I declare:


    > > Foo<std::map<int, std::string> > myFoo2();


    > Again, I believe that you want:


    > Foo<std::map<int, std::string> > myFoo2;


    > > it will use the specialization... and that regardless of the types
    > > used for std::map (in this case, int and std::string), any
    > > "Foo<std::map<typeA, typeB> > myFooExample()" will always
    > > instantiate the specialization.


    > The answer depends on how many template parameters "std::map"
    > requires. The usual number is two - the two specified by the
    > C++ Standard.


    The usual number is four, since that's what the C++ standard
    requires. He has defined a partial specialization for Foo<
    std::map< T, U, std::less<T>, std::allocator< std::pair< T
    const, U > >. If he instantiates Foo with a type which
    corresponds to this, the partial specialization will be used.
    Otherwise, the non-specialized version will be used. Thus, with
    std::map< int, std::string > (or std::map< int, std::string,
    std::less< int > >), he'll get the partial specialization, but
    with std::map< std::string, int, CaseInsensitiveCompare >, he'll
    get the non-specialized version.

    > An implementation however is allowed to require additional
    > temmplate type parameters for a std::map.


    But only if they follow the required four, and have default
    values. So as long as you don't use them, his code should work.

    > So, assuming that std::map requires only two type parameters,
    > then the answer is "yes".


    Assuming that the implementation of std::map is conform, his
    partial specialization will be used for all std::map
    instantiations which use std::less<Key> as the comparator, and
    std::allocator< std::pair< Key const, T > > as the allocator.
    (Using something other than the default allocator is fairly
    rare, but it's quite frequent to find map's with other than the
    default comparison function. In his case, I would definitly add
    that to the arguments of the partial specialization. And it's
    not that difficult to add the allocator either:

    template< typename Key, typename Value,
    typename Cmp, typename Alloc >
    class Foo< std::map< Key, Value, Cmp, Alloc > >
    {
    // ...
    } ;

    This should work for all instanciations of std::map.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, May 15, 2008
    #5
  6. flopbucket

    Greg Herlihy Guest

    On May 14, 3:28 pm, Victor Bazarov <> wrote:
    > Greg Herlihy wrote:
    >
    > > The answer depends on how many template parameters "std::map"
    > > requires. The usual number is two - the two specified by the C++
    > > Standard. An implementation however is allowed to require additional
    > > temmplate type parameters for a std::map. So, assuming that std::map
    > > requires only two type parameters, then the answer is "yes".

    >
    > I don't think it has anything to do with the number of arguments the
    > template takes/has.  The specialisation is not a template with a
    > template template argument (I believe that's what you're thinking of...)
    >
    > For instance,
    >
    >      template<class T, class U = int> class TwoArgs {};
    >      template<class T> struct Foo { enum {a=0}; };
    >      template<class T> struct Foo<TwoArgs<T> > { enum {a=1}; };
    >
    >      int main() {
    >          char should_complain[Foo<char>::a];
    >          char dont_know[Foo<TwoArgs<int,char> >::a];
    >          char should_be_OK[Foo<TwoArgs<double> >::a];
    >      }
    >
    > The declaration of 'should_complain' instantiates the regular 'Foo'
    > because it's not the specialisation on 'TwoArgs'.  The declaration of
    > 'should_be_OK' is the specialisation which has 'a == 1'.  Now, since
    > 'dont_know' uses the 'Foo' instantiated for 'TwoArgs', yet the second
    > argument of 'TwoArgs' is not the default (int), I am not sure.  The
    > Comeau online test drive does not like 'dont_know', most likely because
    > it uses the 'TwoArgs' in a way different from the specialisation's, and
    > as the result 'a' is 0.  Tricky...


    I agree with Comeau compiler that TwoArgs<int,char> will not match the
    provided "TwoArgs" specialization, since "char" is not default
    argument type for TwoArg<>'s second type parameter.

    Anyway, as James points out a std::map actually accepts (at least)
    four template type parameters. Now, since the original program
    specified only two of those four type parameters, the two unspecified
    type parameters assume their default type arguments.

    So, if the program instantiates the Foo template with a std::map class
    that was in turn instantiated with a non-default Allocator class -
    then the std::map specialization will not be selected. Therefore, to
    ensure that any and all std::map classes (no matter their template
    type arguments) always use Foo<>'s std::map specialization, the
    declaration of the Foo template must provide as many type arguments
    for the std::map specialization as a std::map accepts. For example,
    assuming the required four arguments, the declaration of Foo<> should
    look more like this:

    template<class T1, class T2, class T3, class T4>
    class Foo<std::map<T1, T2, T3, T4> >
    {
    // ...
    };

    In that way, std::map's instantiated with non-default template type
    arguments - will still select Foo's partial specialization for
    std::maps.

    Greg
    Greg Herlihy, May 15, 2008
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dave
    Replies:
    4
    Views:
    7,646
    pdixtl
    Jun 4, 2010
  2. pit3k
    Replies:
    8
    Views:
    360
    Victor Bazarov
    Feb 9, 2005
  3. Ruben Campos
    Replies:
    3
    Views:
    6,449
  4. Joseph Turian
    Replies:
    2
    Views:
    455
  5. mliptak
    Replies:
    3
    Views:
    333
    mliptak
    Mar 21, 2007
Loading...

Share This Page