Trying to define a generic template operator for all container classes

Discussion in 'C++' started by Shriramana Sharma, Jun 23, 2013.

  1. Hello.

    I am trying to define an operator<< in my program such that for any container_template_type and value_type, if con is an object of type container_template_type<value_type> and val1, val2, val3 are objects of type value_type, I can chain adding the objects to the container:

    con << val1 << val2 << val3 ;

    So I tried defining it as:

    template < typename C, typename V >
    inline C<V> &
    operator << ( C<V> & con, const V & val ) { con.push_back(val) ; return con; }

    but both GCC 4.8.1 and Clang 3.2 complain about this. GCC says "error: ā€˜Cā€™ is not a template" and Clang says "error: expected unqualified-id".

    I am not sure how to tell the compiler that C is a template type. Please help.

    The code:

    # include <iostream>
    # include <vector>

    template < typename C, typename V >
    inline C<V> &
    operator << ( C<V> & con, const V & val ) { con.push_back(val) ; return con; }

    int main ()
    {
    vector<int> v ;
    v << 1 << 2 << 3 ;
    for ( int i = 0 ; i < v.size() ; ++i ) std::cout << v << ' ' ;
    std::cout << std::endl ;
    }
    Shriramana Sharma, Jun 23, 2013
    #1
    1. Advertising

  2. On Sunday, June 23, 2013 12:51:29 PM UTC+5:30, Shriramana Sharma wrote:
    > template < typename C, typename V >
    > inline C<V> &
    > operator << ( C<V> & con, const V & val ) { con.push_back(val) ; return con ; }


    I had to do:

    template < template<typename,typename> class C, typename V, typename A >
    inline C<V,A> &
    operator << ( C<V,A> & con, const V & val ) { con.push_back(val) ; return con ; }

    to indicate that C is a template class taking two typename template arguments (the second being the allocator which apparently one can't avoid specifying even though it is mostly (?) not used.
    Shriramana Sharma, Jun 23, 2013
    #2
    1. Advertising

  3. Shriramana Sharma

    Nobody Guest

    On Sun, 23 Jun 2013 00:21:29 -0700, Shriramana Sharma wrote:

    > I am trying to define an operator<< in my program such that for any
    > container_template_type and value_type, if con is an object of type
    > container_template_type<value_type> and val1, val2, val3 are objects of
    > type value_type, I can chain adding the objects to the container:
    >
    > con << val1 << val2 << val3 ;
    >
    > So I tried defining it as:
    >
    > template < typename C, typename V >
    > inline C<V> &
    > operator << ( C<V> & con, const V & val )


    Why not just take the complete container type as a parameter and use its
    value_type member:

    template < typename C >
    inline C &
    operator << ( C & con, const typename C::value_type & val ) {

    This way, it doesn't matter how many parameters the container template has.

    Or even just:

    template < typename C, typename V >
    inline C &
    operator << ( C & con, const V & val ) {

    This way the container doesn't even need to be a template.

    The downsides are that passing a value of a convertible type will result
    in an extra instantation for that type, with the conversion being
    performed at the .push_back() call, and that passing a value of a
    non-convertible type will result in a messier error message.
    Nobody, Jun 23, 2013
    #3
  4. Hello thanks for your reply. Comments inline:

    On Sunday, June 23, 2013 10:49:25 PM UTC+5:30, Nobody wrote:
    > Why not just take the complete container type as a parameter and use its
    > value_type member:
    >
    > template < typename C >
    > inline C &
    > operator << ( C & con, const typename C::value_type & val ) {
    > This way, it doesn't matter how many parameters the container template has.


    This method seems OK for inserting values into containers.

    > Or even just:
    > template < typename C, typename V >
    > inline C &
    > operator << ( C & con, const V & val ) {
    > This way the container doesn't even need to be a template.


    This method will work fine if you don't have any iostreams in your program, because if you do, then any attempt to write to an ostream using the operator<< will call this template because it would fit to the described pattern.

    As a related point, it would seem that if I want to write a template to dump the contents of a container to an ostream, it is not possible for me to avoid the template<typename,typename> class thing:

    template < template<typename,typename> class C, typename V, typename A >
    inline ostream & operator << ( ostream & os, const C<V,A> & con )
    {
    for ( typename C<V,A>::const_iterator it = con.begin() ; it != con.end() ; ++it ) os << *it << ' ' ;
    os << endl ;
    return os ;
    }
    Shriramana Sharma, Jun 27, 2013
    #4
    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. Vikas
    Replies:
    1
    Views:
    325
    Victor Bazarov
    Aug 25, 2003
  2. Joe Hesse
    Replies:
    3
    Views:
    463
    want.to.be.professer
    Dec 7, 2007
  3. Replies:
    2
    Views:
    774
  4. Jeremy
    Replies:
    3
    Views:
    393
  5. Stephen Howe
    Replies:
    8
    Views:
    1,517
    Pavel
    Apr 10, 2011
Loading...

Share This Page