how to cause const promotion for template code

Discussion in 'C++' started by Siemel Naran, Nov 30, 2004.

  1. Siemel Naran

    Siemel Naran Guest

    Hi. I have a function

    template <class InputIter, class OutputIter>
    void f(InputIter begin, InputIter end, OutputIter result);

    With c of type char* and cc of type const char*, the code f(c,c,cc) calls
    f<char*, const char *>, which is fine.

    But f(c,c,c) calls a new instantiation f<char*,char*> whereas I'd like it to
    call f<const char*,char*>.

    How to make this happen?
    Siemel Naran, Nov 30, 2004
    #1
    1. Advertising

  2. Siemel Naran wrote in
    news:_%Xqd.74482$ in
    comp.lang.c++:

    > Hi. I have a function
    >
    > template <class InputIter, class OutputIter>
    > void f(InputIter begin, InputIter end, OutputIter result);
    >
    > With c of type char* and cc of type const char*, the code f(c,c,cc)
    > calls f<char*, const char *>, which is fine.


    Well a "char const *" *isn't* an output iterator, which isn't my
    defenition of "fine".

    >
    > But f(c,c,c) calls a new instantiation f<char*,char*> whereas I'd like
    > it to call f<const char*,char*>.


    Why, what difference does it make ?. If you're trying to avoid code bloat
    some modern compilers come with optimizers that can do this for you.

    >
    > How to make this happen?
    >


    template < typename T >
    inline void f( T *a, T *b, T *c )
    {
    f< T const *, T * >( a, b, c );
    }

    Rob.
    --
    http://www.victim-prime.dsl.pipex.com/
    Rob Williscroft, Nov 30, 2004
    #2
    1. Advertising

  3. Siemel Naran

    Siemel Naran Guest

    "Rob Williscroft" <> wrote in message
    > Siemel Naran wrote in


    > > template <class InputIter, class OutputIter>
    > > void f(InputIter begin, InputIter end, OutputIter result);
    > >
    > > With c of type char* and cc of type const char*, the code f(c,c,cc)
    > > calls f<char*, const char *>, which is fine.

    >
    > Well a "char const *" *isn't* an output iterator, which isn't my
    > defenition of "fine".


    Oops. That should have been f(cc,cc,c) which calls f<const char*, char*>
    which is fine.

    > Why, what difference does it make ?. If you're trying to avoid code bloat
    > some modern compilers come with optimizers that can do this for you.


    But some don't, so I have to do it.


    > template < typename T >
    > inline void f( T *a, T *b, T *c )
    > {
    > f< T const *, T * >( a, b, c );
    > }


    First, can one specialize member functions? My function f is actually a
    member function.

    Second, how to handle STL iterators. For example, I want
    f<std::deque<int>::iterator, std::deque<int>::iterator> to call
    f<std::deque<int>::const_iterator, std::deque<int>::iterator>. Do you know
    how to achieve this?

    Thanks.
    Siemel Naran, Nov 30, 2004
    #3
  4. Siemel Naran wrote in
    news:wm3rd.75692$ in
    comp.lang.c++:

    >> Why, what difference does it make ?. If you're trying to avoid code
    >> bloat some modern compilers come with optimizers that can do this for
    >> you.

    >
    > But some don't, so I have to do it.


    Do you know this for a fact, have you measured a performance drop
    because of it ?

    >
    >
    >> template < typename T >
    >> inline void f( T *a, T *b, T *c )
    >> {
    >> f< T const *, T * >( a, b, c );
    >> }

    >
    > First, can one specialize member functions? My function f is actually
    > a member function.


    The above isn't a specialization its an overload, and yes you can
    overload member functions even when they are templates.

    Also you can only explicitly specialze functions. eg:

    template < typename T > void f( T ) {}
    template <> void f< int >( int ) {}

    >
    > Second, how to handle STL iterators. For example, I want
    > f<std::deque<int>::iterator, std::deque<int>::iterator> to call
    > f<std::deque<int>::const_iterator, std::deque<int>::iterator>. Do you
    > know how to achieve this?
    >


    It can't be done as there is now way of getting a const_iterator
    given *only* an iterator (except when the iterator is a pointer).

    Rob.
    --
    http://www.victim-prime.dsl.pipex.com/
    Rob Williscroft, Nov 30, 2004
    #4
  5. Siemel Naran wrote:
    > "Rob Williscroft" <> wrote in message
    > > template < typename T >
    > > inline void f( T *a, T *b, T *c )
    > > {
    > > f< T const *, T * >( a, b, c );
    > > }

    >
    > First, can one specialize member functions? My function f is

    actually a
    > member function.


    How is this question related to the above function? This is not a
    specialization but an overload and you surely can overload member
    functions. Other than this, the answer to your question is: no.
    Actually, you can only fully specialize global functions while you
    would require a partial specialization anyway.

    > Second, how to handle STL iterators. For example, I want
    > f<std::deque<int>::iterator, std::deque<int>::iterator> to call
    > f<std::deque<int>::const_iterator, std::deque<int>::iterator>.


    Since there is no requirement that an iterator has a constant
    counterpart, there is no requirement for something like
    'const_iterator' in iterator traits. You might get away by
    using your own traits class:

    template <typename It> struct const_it { typedef It type; };
    template <typename T> struct const_it<T*> { typedef T const* type; };
    template <typename T, typename A>
    struct const_it<std::deque<T, A>::iterator> {
    typedef std::deque<T, A>::const_iterator type;
    };
    // ...

    .... and use this in your function's implementation:

    template <typename InputIter, typename OutputIter>
    OutputIter f(InputIter beg, InputIter end, OutputIter to) {
    return f<typename const_it<InputIter>::type, OutputIter>(beg, end,
    to);
    }

    A complication is that 'std::vector<T>'s iterator may actually be
    'T*' in which case you would attempt to specialize twice for the
    type 'T*' if you added vector's iterator to the above specialization.
    --
    <mailto:> <http://www.dietmar-kuehl.de/>
    <http://www.contendix.com> - Software Development & Consulting
    Dietmar Kuehl, Nov 30, 2004
    #5
  6. Siemel Naran wrote:
    > "Rob Williscroft" <> wrote in message
    > > template < typename T >
    > > inline void f( T *a, T *b, T *c )
    > > {
    > > f< T const *, T * >( a, b, c );
    > > }

    >
    > First, can one specialize member functions? My function f is

    actually a
    > member function.


    How is this question related to the above function? This is not a
    specialization but an overload and you surely can overload member
    functions. Other than this, the answer to your question is: no.
    Actually, you can only fully specialize global functions while you
    would require a partial specialization anyway.

    > Second, how to handle STL iterators. For example, I want
    > f<std::deque<int>::iterator, std::deque<int>::iterator> to call
    > f<std::deque<int>::const_iterator, std::deque<int>::iterator>.


    Since there is no requirement that an iterator has a constant
    counterpart, there is no requirement for something like
    'const_iterator' in iterator traits. You might get away by
    using your own traits class:

    template <typename It> struct const_it { typedef It type; };
    template <typename T> struct const_it<T*> { typedef T const* type; };
    template <typename T, typename A>
    struct const_it<std::deque<T, A>::iterator> {
    typedef std::deque<T, A>::const_iterator type;
    };
    // ...

    .... and use this in your function's implementation:

    template <typename InputIter, typename OutputIter>
    OutputIter f(InputIter beg, InputIter end, OutputIter to) {
    return f<typename const_it<InputIter>::type, OutputIter>(beg, end,
    to);
    }

    A complication is that 'std::vector<T>'s iterator may actually be
    'T*' in which case you would attempt to specialize twice for the
    type 'T*' if you added vector's iterator to the above specialization.
    --
    <mailto:> <http://www.dietmar-kuehl.de/>
    <http://www.contendix.com> - Software Development & Consulting
    Dietmar Kuehl, Nov 30, 2004
    #6
  7. Siemel Naran

    Siemel Naran Guest

    "Dietmar Kuehl" <> wrote in message
    > Siemel Naran wrote:


    > > First, can one specialize member functions? My function f is


    > How is this question related to the above function? This is not a
    > specialization but an overload and you surely can overload member
    > functions. Other than this, the answer to your question is: no.


    Why can one not specialize member functions?


    > Since there is no requirement that an iterator has a constant
    > counterpart, there is no requirement for something like
    > 'const_iterator' in iterator traits. You might get away by
    > using your own traits class:
    >
    > template <typename It> struct const_it { typedef It type; };
    > template <typename T> struct const_it<T*> { typedef T const* type; };
    > template <typename T, typename A>
    > struct const_it<std::deque<T, A>::iterator> {
    > typedef std::deque<T, A>::const_iterator type;
    > };
    > // ...
    >
    > ... and use this in your function's implementation:
    >
    > template <typename InputIter, typename OutputIter>
    > OutputIter f(InputIter beg, InputIter end, OutputIter to) {
    > return f<typename const_it<InputIter>::type, OutputIter>(beg, end,
    > to);
    > }
    >
    > A complication is that 'std::vector<T>'s iterator may actually be
    > 'T*' in which case you would attempt to specialize twice for the
    > type 'T*' if you added vector's iterator to the above specialization.


    Yes, this is a good idea. BTW, is the following legal in a fully ANSI
    compliant compiler

    template <typename Container>
    struct const_it<typename Container::iterator> {
    typedef typename Container::const_iterator type;
    };

    I guess not, because the compiler might have a hard time deducing
    'Container' given a specialization const_it<MyIter>.


    But it gets me thinking to a new solution.

    template <class Container, class InputIter, class OutputIter>
    void f(const Container&, typename Container::const_iterator begin, typename
    Container::const_iterator end, OutputIter result);

    We explicitly pass in the container in order that we can use
    Container::const_iterator. There will be a specialization

    template <class T, class OutputIter>
    void f<const T*,const T*, OutputIter>(const T*, const T* begin, const T*
    end, OutputIter result);
    Siemel Naran, Dec 2, 2004
    #7
  8. Siemel Naran wrote:
    > Why can one not specialize member functions?


    Because it is sufficient to overload them.

    > BTW, is the following legal in a fully ANSI compliant compiler
    >
    > template <typename Container>
    > struct const_it<typename Container::iterator> {
    > typedef typename Container::const_iterator type;
    > };


    No: the container cannot be deduced if two containers share a common
    iterator type. Still, the typedefs of related types may differ
    for the two containers. The same is true for argument type deduction
    in function templates: you cannot use a nested type.

    > But it gets me thinking to a new solution.
    >
    > template <class Container, class InputIter, class OutputIter>
    > void f(const Container&, typename Container::const_iterator begin,

    typename
    > Container::const_iterator end, OutputIter result);


    In this case, I'd go with a "range" which would be a pair of member
    function ('begin()' and 'end()'; optionally also 'rbegin()' and
    'rend()' for reversible ranges) plus a set of supporting typedefs.
    The function would than just get one parameter for the input sequence,
    namely the range.
    --
    <mailto:> <http://www.dietmar-kuehl.de/>
    <http://www.contendix.com> - Software Development & Consulting
    Dietmar Kuehl, Dec 2, 2004
    #8
    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. Replies:
    11
    Views:
    1,083
  2. Javier
    Replies:
    2
    Views:
    533
    James Kanze
    Sep 4, 2007
  3. 0m
    Replies:
    26
    Views:
    1,082
    Tim Rentsch
    Nov 10, 2008
  4. fungus
    Replies:
    13
    Views:
    864
    fungus
    Oct 31, 2008
  5. Replies:
    2
    Views:
    519
    Andrew Koenig
    Feb 9, 2009
Loading...

Share This Page