A question about Template parameter

Discussion in 'C++' started by Saeed Amrollahi, Jun 13, 2010.

  1. Dear All
    Hi

    C++ allow to declare templates with various kind of template
    parameters.
    I wonder what are the applications of these two template parameters:
    1. template<class> // no identifier for template parameter
    class C1 {
    };

    How it differs from this one:
    template<class T>
    class C2 {
    };

    C1<int> c1;
    C2<int> c2;

    2. template template parameter:
    template<template<class T> class A>
    struct B {
    A<int> a;
    };

    How it differs from this one:
    template<class T> class A { /* ... */ };
    struct B {
    A<int> a;
    };

    In advance, than you for your help.
    -- Saeed Amrollahi
     
    Saeed Amrollahi, Jun 13, 2010
    #1
    1. Advertising

  2. Saeed Amrollahi <> wrote:
    > Dear All
    > Hi
    >
    > C++ allow to declare templates with various kind of template
    > parameters.
    > I wonder what are the applications of these two template parameters:
    > 1. template<class> // no identifier for template parameter
    >     class C1 {
    >     };
    >
    > How it differs from this one:
    >     template<class T>
    >     class C2 {
    >     };
    >
    >    C1<int> c1;
    >    C2<int> c2;


    There is no difference, C1 omits to give a name to something that
    wouldn't be used in any case.

    I suppose that those template declarations should result in the
    declaration of the following two classes:

    class C1 {
    };

    class C2 {
    };

    whatever the amount of different instantiations, but different
    instantiations still are considered as different types, hence you will
    not be able to assign a C1<double> to a C1<int> and thus I suppose the
    compiler will create something like

    class C1_int {
    };

    class C1_double {
    };

    or whatever other mechanism to disambiguate at runtime.

    I can see uses of such a simple template (e.g. exception objects to be
    thrown and caught on a per-template-parameter-type basis)

    > 2. template template parameter:
    >   template<template<class T> class A>
    >   struct B {
    >     A<int> a;
    >   };
    >
    > How it differs from this one:
    > template<class T> class A { /* ... */ };
    > struct B {
    >   A<int> a;
    >
    > };


    The former is a single declaration, where the A class doesn't exist
    outside of B, the latter is a double declaration (two different
    classes are declared and can be used separately).

    At least that's what I understand about all of this, hope that helps.

    --
    FSC
    http://userscripts.org/scripts/show/59948
     
    Francesco S. Carta, Jun 13, 2010
    #2
    1. Advertising

  3. On Jun 13, 2:06 pm, "Francesco S. Carta" <> wrote:
    > Saeed Amrollahi <> wrote:
    > > Dear All
    > > Hi

    >
    > > C++ allow to declare templates with various kind of template
    > > parameters.
    > > I wonder what are the applications of these two template parameters:
    > > 1. template<class> // no identifier for template parameter
    > >     class C1 {
    > >     };

    >
    > > How it differs from this one:
    > >     template<class T>
    > >     class C2 {
    > >     };

    >
    > >    C1<int> c1;
    > >    C2<int> c2;

    >
    > There is no difference, C1 omits to give a name to something that
    > wouldn't be used in any case.
    >
    > I suppose that those template declarations should result in the
    > declaration of the following two classes:
    >
    > class C1 {
    >
    > };
    >
    > class C2 {
    >
    > };
    >
    > whatever the amount of different instantiations, but different
    > instantiations still are considered as different types, hence you will
    > not be able to assign a C1<double> to a C1<int> and thus I suppose the
    > compiler will create something like
    >
    > class C1_int {
    >
    > };
    >
    > class C1_double {
    >
    > };
    >
    > or whatever other mechanism to disambiguate at runtime.
    >
    > I can see uses of such a simple template (e.g. exception objects to be
    > thrown and caught on a per-template-parameter-type basis)
    >
    > > 2. template template parameter:
    > >   template<template<class T> class A>
    > >   struct B {
    > >     A<int> a;
    > >   };

    >
    > > How it differs from this one:
    > > template<class T> class A { /* ... */ };
    > > struct B {
    > >   A<int> a;

    >
    > > };

    >
    > The former is a single declaration, where the A class doesn't exist
    > outside of B, the latter is a double declaration (two different
    > classes are declared and can be used separately).
    >
    > At least that's what I understand about all of this, hope that helps.
    >
    > --
    > FSChttp://userscripts.org/scripts/show/59948


    Hi Francesco
    Thanks for your clarification.
    About question 1, I'm not convinced yet.
    Why there is such facility in the language:
    template<class>
    class A {
    /* there is no template parameter identifier */
    int a;
    };

    A<int> a;
    what is the advantage of such parameterization compare to
    the plain class:
    class A {
    int a;
    };

    Regards,
    -- Saeed Amrollahi
     
    Saeed Amrollahi, Jun 13, 2010
    #3
  4. Francesco S. Carta <> wrote:
    > I can see uses of such a simple template


    There are situations where you want to declare (not define, but declare)
    a template class. When you are doing such a declaration, you don't need the
    template parameter for anything, and thus you can omit it.

    One practical situation where you may need to do that is when declaring
    a template class to be a friend of another class (something which
    surprisingly few C++ programmers know how to do). In other words, something
    like:

    class A
    {
    template<typename> friend class B;
    ...
    };

    Here we are declaring that class B, which is a template class, is a
    friend class of A. You could specify a name for the template parameter,
    but since it's not used in the declaration, it can be omitted.

    Complete example:

    #include <iostream>

    class A
    {
    template<typename> friend class B;
    int i;

    public:
    A(int value): i(value) {}
    };

    template<typename T>
    class B
    {
    public:
    void foo(const A& obj) { std::cout << obj.i << std::endl; }
    };

    int main()
    {
    A a(5);
    B<int> b;
    b.foo(a);
    }
     
    Juha Nieminen, Jun 13, 2010
    #4
  5. Saeed Amrollahi <> wrote:
    > On Jun 13, 2:06 pm, "Francesco S. Carta" <> wrote:
    >
    >
    >
    > > Saeed Amrollahi <> wrote:
    > > > Dear All
    > > > Hi

    >
    > > > C++ allow to declare templates with various kind of template
    > > > parameters.
    > > > I wonder what are the applications of these two template parameters:
    > > > 1. template<class> // no identifier for template parameter
    > > >     class C1 {
    > > >     };

    >
    > > > How it differs from this one:
    > > >     template<class T>
    > > >     class C2 {
    > > >     };

    >
    > > >    C1<int> c1;
    > > >    C2<int> c2;

    >
    > > There is no difference, C1 omits to give a name to something that
    > > wouldn't be used in any case.

    >
    > > I suppose that those template declarations should result in the
    > > declaration of the following two classes:

    >
    > > class C1 {

    >
    > > };

    >
    > > class C2 {

    >
    > > };

    >
    > > whatever the amount of different instantiations, but different
    > > instantiations still are considered as different types, hence you will
    > > not be able to assign a C1<double> to a C1<int> and thus I suppose the
    > > compiler will create something like

    >
    > > class C1_int {

    >
    > > };

    >
    > > class C1_double {

    >
    > > };

    >
    > > or whatever other mechanism to disambiguate at runtime.

    >
    > > I can see uses of such a simple template (e.g. exception objects to be
    > > thrown and caught on a per-template-parameter-type basis)

    >
    > > > 2. template template parameter:
    > > >   template<template<class T> class A>
    > > >   struct B {
    > > >     A<int> a;
    > > >   };

    >
    > > > How it differs from this one:
    > > > template<class T> class A { /* ... */ };
    > > > struct B {
    > > >   A<int> a;

    >
    > > > };

    >
    > > The former is a single declaration, where the A class doesn't exist
    > > outside of B, the latter is a double declaration (two different
    > > classes are declared and can be used separately).

    >
    > > At least that's what I understand about all of this, hope that helps.

    >
    > > --
    > > FSChttp://userscripts.org/scripts/show/59948

    >
    > Hi Francesco
    > Thanks for your clarification.
    > About question 1, I'm not convinced yet.
    > Why there is such facility in the language:
    >   template<class>
    >   class A {
    >     /* there is no template parameter identifier */
    >     int a;
    >   };
    >
    >   A<int> a;
    > what is the advantage of such parameterization compare to
    > the plain class:
    >   class A {
    >     int a;
    >   };
    >
    > Regards,
    >   -- Saeed Amrollahi


    I was about to post a weird example about how to use such a feature
    with exceptions, but Juha dropped in with something different which I
    happened not to know, and I think it's a far better example than mine
    - hence I'll keep my example in my clipboard ;-)

    --
    FSC
    http://userscripts.org/scripts/show/59948
     
    Francesco S. Carta, Jun 13, 2010
    #5
  6. Juha Nieminen <> wrote:
    > Francesco S. Carta <> wrote:
    >
    > > I can see uses of such a simple template

    >
    >   There are situations where you want to declare (not define, but declare)
    > a template class. When you are doing such a declaration, you don't need the
    > template parameter for anything, and thus you can omit it.
    >
    >   One practical situation where you may need to do that is when declaring
    > a template class to be a friend of another class (something which
    > surprisingly few C++ programmers know how to do). In other words, something
    > like:
    >
    >     class A
    >     {
    >         template<typename> friend class B;
    >         ...
    >     };
    >
    >   Here we are declaring that class B, which is a template class, is a
    > friend class of A. You could specify a name for the template parameter,
    > but since it's not used in the declaration, it can be omitted.
    >
    >   Complete example:
    >
    > #include <iostream>
    >
    > class A
    > {
    >     template<typename> friend class B;
    >     int i;
    >
    >  public:
    >     A(int value): i(value) {}
    >
    > };
    >
    > template<typename T>
    > class B
    > {
    >  public:
    >     void foo(const A& obj) { std::cout << obj.i << std::endl; }
    >
    > };
    >
    > int main()
    > {
    >     A a(5);
    >     B<int> b;
    >     b.foo(a);
    >
    > }
    >
    >


    Well, I'm among those that didn't know that, indeed, thanks a lot for
    pointing that out, it will come useful for sure - interesting thread.

    --
    FSC
    http://userscripts.org/scripts/show/59948
     
    Francesco S. Carta, Jun 13, 2010
    #6
  7. Saeed Amrollahi <> writes:

    > C++ allow to declare templates with various kind of template
    > parameters.
    > I wonder what are the applications of these two template parameters:
    > 1. template<class> // no identifier for template parameter
    > class C1 {
    > };
    >
    > How it differs from this one:
    > template<class T>
    > class C2 {
    > };
    >
    > C1<int> c1;
    > C2<int> c2;


    As given there is essentially no difference since, with the
    definition of both C1 and C2, you make no use of the template
    parameter type. Note: it would be /possible/ to do so in the case of
    C2, but not for C1 since the parameter is not named.

    This is really no different than what you find in the case of ordinary
    function calls that use unnamed function call parameters:

    #include <iostream>

    void f(int) // unnamed function call parameter - int
    {
    std::cout << "Calling void f(int)...\n";
    }

    void f(char c) // named function call parameter - char
    {
    std::cout << "Calling void f(char c) "
    << "with c = '" << c << "'...\n";
    }

    int main()
    {
    f(1);
    f('1');
    }

    /**
    * Output:
    * Calling void f(int)...
    * Calling void f(char c) with c = '1'...
    */

    Again, inside the body of void f(char c) the function call argument
    /could/ be used, since it is named, but not inside the body of void
    f(int).

    Note: in the case of C1, even though the template parameter is not
    named (and so cannot be used in the definition of the class) the
    compiler still knows what the template argument is that matches it
    and so it can be `reconstructed' later, elsewhere. Consider:

    #include <string>
    #include <iostream>

    template<class> // unnamed template parameter, but...
    class C1 { };

    template<class T>
    std::string print_type();

    template<>
    std::string print_type<int>()
    {
    return "T = int";
    }

    template<class T>
    void f(C1<T>) // ... T can still be deduced here
    {
    std::cout << "Calling void f(C1<T>) with ["
    << print_type<T>()
    << "]...\n";
    }

    int main()
    {
    C1<int> c1;
    f(c1);
    }

    /**
    * Output:
    * Calling void f(C1<T>) with [T = int]...
    */

    > 2. template template parameter:
    > template<template<class T> class A>
    > struct B {
    > A<int> a;
    > };
    >
    > How it differs from this one:
    > template<class T> class A { /* ... */ };
    > struct B {
    > A<int> a;
    > };


    In the case of your second type B, the type of the member a is hard
    coded: it is your class A. For your first type B, however, A is a
    template template parameter and so it can be matched by other template
    types, for instance:

    template<class T> class NotA { /* ... */ };
    B<NotA> b;

    Note, also, that there is a difference in the syntax of declarations.
    For the first you have to specify a template argument, which is not
    the case for the second.

    Regards

    Paul Bibbings
     
    Paul Bibbings, Jun 13, 2010
    #7
  8. Saeed Amrollahi <> writes:

    > About question 1, I'm not convinced yet.
    > Why there is such facility in the language:
    > template<class>
    > class A {
    > /* there is no template parameter identifier */
    > int a;
    > };
    >
    > A<int> a;
    > what is the advantage of such parameterization compare to
    > the plain class:
    > class A {
    > int a;
    > };


    In your example as given there is no advantage. For your first
    definition you have parameterized A for no reason at all. However, this
    does not have any bearing on whether there /are/ reasons for which a
    type may be parameterized where the name of the parameter is not used
    *directly* in the definition of the class itself.

    The following is perhaps not the best example, but hopefully illustrates
    possible uses. Here, the parameterization of select_on_type<> is used
    to control which types of ShortOrIntOnly may be instantiated:

    template<class> struct select_on_type { }; // #1

    template<>
    struct select_on_type<short> {
    typedef short type;
    };

    template<>
    struct select_on_type<int> {
    typedef int type;
    };

    template<
    typename T,
    template <class> class Selector = select_on_type // #2
    >

    struct ShortOrIntOnly {
    typename Selector<T>::type t;
    };

    int main()
    {
    ShortOrIntOnly<short> soi1; // OK
    ShortOrIntOnly<int> soi2; // OK
    ShortOrIntOnly<char> soi3; // Error
    }

    In the above code you will see a couple of places (#1 and #2) where it
    is appropriate to use the syntax template<class> without requiring an
    identifier for the template parameter. The syntax, as used here, does
    not detract from the purpose of the type as it is intended to be used
    (as a `selector'). It is just that your example omits the identifier for
    no purpose whatsoever.

    Regards

    Paul Bibbings
     
    Paul Bibbings, Jun 13, 2010
    #8
  9. On Jun 13, 2:06 pm, "Francesco S. Carta" <> wrote:
    > Saeed Amrollahi <> wrote:
    > > Dear All
    > > Hi

    >
    > > C++ allow to declare templates with various kind of template
    > > parameters.
    > > I wonder what are the applications of these two template parameters:
    > > 1. template<class> // no identifier for template parameter
    > >     class C1 {
    > >     };

    >
    > > How it differs from this one:
    > >     template<class T>
    > >     class C2 {
    > >     };

    >
    > >    C1<int> c1;
    > >    C2<int> c2;

    >
    > There is no difference, C1 omits to give a name to something that
    > wouldn't be used in any case.
    >
    > I suppose that those template declarations should result in the
    > declaration of the following two classes:
    >
    > class C1 {
    >
    > };
    >
    > class C2 {
    >
    > };
    >
    > whatever the amount of different instantiations, but different
    > instantiations still are considered as different types, hence you will
    > not be able to assign a C1<double> to a C1<int> and thus I suppose the
    > compiler will create something like
    >
    > class C1_int {
    >
    > };
    >
    > class C1_double {
    >
    > };
    >
    > or whatever other mechanism to disambiguate at runtime.
    >
    > I can see uses of such a simple template (e.g. exception objects to be
    > thrown and caught on a per-template-parameter-type basis)
    >
    > > 2. template template parameter:
    > >   template<template<class T> class A>
    > >   struct B {
    > >     A<int> a;
    > >   };

    >
    > > How it differs from this one:
    > > template<class T> class A { /* ... */ };
    > > struct B {
    > >   A<int> a;

    >
    > > };

    >
    > The former is a single declaration, where the A class doesn't exist
    > outside of B, the latter is a double declaration (two different
    > classes are declared and can be used separately).
    >
    > At least that's what I understand about all of this, hope that helps.
    >
    > --
    > FSChttp://userscripts.org/scripts/show/59948


    I was out of office for a day.
    Thank you for providing insight.
    -- Saeed Amrollahi
     
    Saeed Amrollahi, Jun 15, 2010
    #9
  10. On Jun 13, 4:06 pm, Juha Nieminen <> wrote:
    > Francesco S. Carta <> wrote:
    >
    > > I can see uses of such a simple template

    >
    >   There are situations where you want to declare (not define, but declare)
    > a template class. When you are doing such a declaration, you don't need the
    > template parameter for anything, and thus you can omit it.
    >
    >   One practical situation where you may need to do that is when declaring
    > a template class to be a friend of another class (something which
    > surprisingly few C++ programmers know how to do). In other words, something
    > like:
    >
    >     class A
    >     {
    >         template<typename> friend class B;
    >         ...
    >     };
    >
    >   Here we are declaring that class B, which is a template class, is a
    > friend class of A. You could specify a name for the template parameter,
    > but since it's not used in the declaration, it can be omitted.
    >
    >   Complete example:
    >
    > #include <iostream>
    >
    > class A
    > {
    >     template<typename> friend class B;
    >     int i;
    >
    >  public:
    >     A(int value): i(value) {}
    >
    > };
    >
    > template<typename T>
    > class B
    > {
    >  public:
    >     void foo(const A& obj) { std::cout << obj.i << std::endl; }
    >
    > };
    >
    > int main()
    > {
    >     A a(5);
    >     B<int> b;
    >     b.foo(a);
    >
    > }
    >
    >


    Hi Juha
    Sorry, for delay. I was out of office for a day.
    It's cool application of unnamed template parameter.
    Thank you for providing insight.
    -- Saeed Amrollahi
     
    Saeed Amrollahi, Jun 15, 2010
    #10
  11. On Jun 13, 5:07 pm, Paul Bibbings <> wrote:
    > Saeed Amrollahi <> writes:
    > > About question 1, I'm not convinced yet.
    > > Why there is such facility in the language:
    > >   template<class>
    > >   class A {
    > >     /* there is no template parameter identifier */
    > >     int a;
    > >   };

    >
    > >   A<int> a;
    > > what is the advantage of such parameterization compare to
    > > the plain class:
    > >   class A {
    > >     int a;
    > >   };

    >
    > In your example as given there is no advantage.  For your first
    > definition you have parameterized A for no reason at all.  However, this
    > does not have any bearing on whether there /are/ reasons for which a
    > type may be parameterized where the name of the parameter is not used
    > *directly* in the definition of the class itself.
    >
    > The following is perhaps not the best example, but hopefully illustrates
    > possible uses.  Here, the parameterization of select_on_type<> is used
    > to control which types of ShortOrIntOnly may be instantiated:
    >
    >    template<class> struct select_on_type { };              // #1
    >
    >    template<>
    >    struct select_on_type<short> {
    >       typedef short type;
    >    };
    >
    >    template<>
    >    struct select_on_type<int> {
    >       typedef int type;
    >    };
    >
    >    template<
    >       typename T,
    >       template <class> class Selector = select_on_type     // #2
    >    >
    >    struct ShortOrIntOnly {
    >       typename Selector<T>::type t;
    >    };
    >
    >    int main()
    >    {
    >       ShortOrIntOnly<short> soi1;     // OK
    >       ShortOrIntOnly<int>   soi2;     // OK
    >       ShortOrIntOnly<char>  soi3;     // Error
    >    }
    >
    > In the above code you will see a couple of places (#1 and #2) where it
    > is appropriate to use the syntax template<class> without requiring an
    > identifier for the template parameter.  The syntax, as used here, does
    > not detract from the purpose of the type as it is intended to be used
    > (as a `selector'). It is just that your example omits the identifier for
    > no purpose whatsoever.
    >
    > Regards
    >
    > Paul Bibbings


    Hi Paul
    Sorry, for delay. I was out of office for a day.
    Thank you for providing detailed answer
    -- Saeed Amrollahi
     
    Saeed Amrollahi, Jun 15, 2010
    #11
    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. Chris Theis
    Replies:
    2
    Views:
    500
    Chris Theis
    Jul 24, 2003
  2. tom_usenet
    Replies:
    0
    Views:
    566
    tom_usenet
    Jul 24, 2003
  3. Gianni Mariani
    Replies:
    1
    Views:
    366
    tom_usenet
    Sep 5, 2003
  4. Stuart Redmann
    Replies:
    5
    Views:
    527
    Stuart Redmann
    Dec 14, 2007
  5. Isti
    Replies:
    2
    Views:
    759
Loading...

Share This Page