Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #5219 > unrolled thread

Overloading a template member function with a dependent name

Started bymlimber <mlimber@gmail.com>
First post2011-05-20 13:37 -0700
Last post2011-05-21 01:47 +0200
Articles 7 — 3 participants

Back to article view | Back to comp.lang.c++


Contents

  Overloading a template member function with a dependent name mlimber <mlimber@gmail.com> - 2011-05-20 13:37 -0700
    Re: Overloading a template member function with a dependent name mlimber <mlimber@gmail.com> - 2011-05-20 14:09 -0700
    Re: Overloading a template member function with a dependent name "Alf P. Steinbach /Usenet" <alf.p.steinbach+usenet@gmail.com> - 2011-05-20 23:21 +0200
      Re: Overloading a template member function with a dependent name mlimber <mlimber@gmail.com> - 2011-05-20 14:21 -0700
        Re: Overloading a template member function with a dependent name "Alf P. Steinbach /Usenet" <alf.p.steinbach+usenet@gmail.com> - 2011-05-21 01:30 +0200
    Re: Overloading a template member function with a dependent name Ruben Safir <mrbrklyn@panix.com> - 2011-05-20 23:33 +0000
      Re: Overloading a template member function with a dependent name "Alf P. Steinbach /Usenet" <alf.p.steinbach+usenet@gmail.com> - 2011-05-21 01:47 +0200

#5219 — Overloading a template member function with a dependent name

Frommlimber <mlimber@gmail.com>
Date2011-05-20 13:37 -0700
SubjectOverloading a template member function with a dependent name
Message-ID<1679ca72-2e81-4fb5-9e8c-ff2a89a7cfff@x38g2000pri.googlegroups.com>
I'm trying to overload a template member function with a dependent
name involved. The following does not work as I'd like:

 class C
 {
 public:
   template<class Iter>
   void Foo( Iter )
   {
     std::cout << "Normal\n";
   }

   template<class T, std::size_t N>
   void Foo( typename std::tr1::array<T,N>::iterator )
   {
     std::cout << "Special\n";
   }
 };

 int main()
 {
   C c;
   std::tr1::array<int,10> a1;
   c.Foo( a1.begin() ); // Doesn't print "Special"!
 }

How can I get that last line in main() to invoke the special C::Foo()?

[toc] | [next] | [standalone]


#5220

Frommlimber <mlimber@gmail.com>
Date2011-05-20 14:09 -0700
Message-ID<b148f633-6598-4fde-98c3-be412553e2ee@f11g2000vbx.googlegroups.com>
In reply to#5219
On May 20, 4:37 pm, mlimber <mlim...@gmail.com> wrote:
[snip]
>    template<class T, std::size_t N>
>    void Foo( typename std::tr1::array<T,N>::iterator )
[snip]

One additional note: I can't use T* as a work-around here because in
VS2010's implementation, std::tr1::array<T,N>::iterator is the
internal type "_Array_iterator<_Ty, _Size>", which is a checked
iterator (at least in debug mode).

Cheers! --M

[toc] | [prev] | [next] | [standalone]


#5221

From"Alf P. Steinbach /Usenet" <alf.p.steinbach+usenet@gmail.com>
Date2011-05-20 23:21 +0200
Message-ID<ir6lm7$tu7$1@dont-email.me>
In reply to#5219
* mlimber, on 20.05.2011 22:37:
> I'm trying to overload a template member function with a dependent
> name involved. The following does not work as I'd like:
>
>   class C
>   {
>   public:
>     template<class Iter>
>     void Foo( Iter )
>     {
>       std::cout<<  "Normal\n";
>     }
>
>     template<class T, std::size_t N>
>     void Foo( typename std::tr1::array<T,N>::iterator )
>     {
>       std::cout<<  "Special\n";
>     }
>   };
>
>   int main()
>   {
>     C c;
>     std::tr1::array<int,10>  a1;
>     c.Foo( a1.begin() ); // Doesn't print "Special"!
>   }
>
> How can I get that last line in main() to invoke the special C::Foo()?

Why there is a problem:

<code>
     template< class Type >
     struct Foo
     {
         typedef int     T;
     };

     template< class Type >
     void foo( typename Type::T ) {}

     int main()
     {
         foo( 666 );     // !Nope
     }
</code>

This does not compile because the compiler cannot deduce the template parameter. 
It cannot because it would be an unbounded reverse lookup: given the actual 
argument type `int`, find the type `Type` that has a member typedef of `T` with 
type `int`. There can be zillions or none of such types.

There are techniques that sometimes can be used to still do something /like/ you 
seem to be aiming for.

One crucial question for applicability of such techniques here is N: do you need 
to know it? In that case I don't know any solution other than changing the 
design. I don't think it can be inferred from the iterator type, at all.


Cheers & hth.,

- Alf  "hungry"

-- 
blog at <url: http://alfps.wordpress.com>

[toc] | [prev] | [next] | [standalone]


#5222

Frommlimber <mlimber@gmail.com>
Date2011-05-20 14:21 -0700
Message-ID<6dbcdcdd-52ca-44c6-842d-4f0f4420f63b@y19g2000yqk.googlegroups.com>
In reply to#5221
On May 20, 5:21 pm, "Alf P. Steinbach /Usenet" <alf.p.steinbach
+use...@gmail.com> wrote:
> * mlimber, on 20.05.2011 22:37:
> > I'm trying to overload a template member function with a dependent
> > name involved. The following does not work as I'd like:
>
> >   class C
> >   {
> >   public:
> >     template<class Iter>
> >     void Foo( Iter )
> >     {
> >       std::cout<<  "Normal\n";
> >     }
>
> >     template<class T, std::size_t N>
> >     void Foo( typename std::tr1::array<T,N>::iterator )
> >     {
> >       std::cout<<  "Special\n";
> >     }
> >   };
>
> >   int main()
> >   {
> >     C c;
> >     std::tr1::array<int,10>  a1;
> >     c.Foo( a1.begin() ); // Doesn't print "Special"!
> >   }
>
> > How can I get that last line in main() to invoke the special C::Foo()?
>
> Why there is a problem:
>
> <code>
>      template< class Type >
>      struct Foo
>      {
>          typedef int     T;
>      };
>
>      template< class Type >
>      void foo( typename Type::T ) {}
>
>      int main()
>      {
>          foo( 666 );     // !Nope
>      }
> </code>
>
> This does not compile because the compiler cannot deduce the template parameter.
> It cannot because it would be an unbounded reverse lookup: given the actual
> argument type `int`, find the type `Type` that has a member typedef of `T` with
> type `int`. There can be zillions or none of such types.
>
> There are techniques that sometimes can be used to still do something /like/ you
> seem to be aiming for.
>
> One crucial question for applicability of such techniques here is N: do you need
> to know it? In that case I don't know any solution other than changing the
> design. I don't think it can be inferred from the iterator type, at all.

Thanks, Alf. I don't need N (it would be sugar to have it, but since
I'm actually passing in begin and end, I can calculate it). So do
tell!

Cheers! --M

[toc] | [prev] | [next] | [standalone]


#5223

From"Alf P. Steinbach /Usenet" <alf.p.steinbach+usenet@gmail.com>
Date2011-05-21 01:30 +0200
Message-ID<ir6t5h$cik$1@dont-email.me>
In reply to#5222
* mlimber, on 20.05.2011 23:21:
> On May 20, 5:21 pm, "Alf P. Steinbach /Usenet"<alf.p.steinbach
> +use...@gmail.com>  wrote:
>> * mlimber, on 20.05.2011 22:37:
>>> I'm trying to overload a template member function with a dependent
>>> name involved. The following does not work as I'd like:
>>
>>>    class C
>>>    {
>>>    public:
>>>      template<class Iter>
>>>      void Foo( Iter )
>>>      {
>>>        std::cout<<    "Normal\n";
>>>      }
>>
>>>      template<class T, std::size_t N>
>>>      void Foo( typename std::tr1::array<T,N>::iterator )
>>>      {
>>>        std::cout<<    "Special\n";
>>>      }
>>>    };
>>
>>>    int main()
>>>    {
>>>      C c;
>>>      std::tr1::array<int,10>    a1;
>>>      c.Foo( a1.begin() ); // Doesn't print "Special"!
>>>    }
>>
>>> How can I get that last line in main() to invoke the special C::Foo()?
>>
>> Why there is a problem:
>>
>> <code>
>>       template<  class Type>
>>       struct Foo
>>       {
>>           typedef int     T;
>>       };
>>
>>       template<  class Type>
>>       void foo( typename Type::T ) {}
>>
>>       int main()
>>       {
>>           foo( 666 );     // !Nope
>>       }
>> </code>
>>
>> This does not compile because the compiler cannot deduce the template parameter.
>> It cannot because it would be an unbounded reverse lookup: given the actual
>> argument type `int`, find the type `Type` that has a member typedef of `T` with
>> type `int`. There can be zillions or none of such types.
>>
>> There are techniques that sometimes can be used to still do something /like/ you
>> seem to be aiming for.
>>
>> One crucial question for applicability of such techniques here is N: do you need
>> to know it? In that case I don't know any solution other than changing the
>> design. I don't think it can be inferred from the iterator type, at all.
>
> Thanks, Alf. I don't need N (it would be sugar to have it, but since
> I'm actually passing in begin and end, I can calculate it). So do
> tell!

Uh, I don't have a suitable implementation to test with, since the g++ 4.4.1 
tr1/array has just raw pointers as iterators. Not much can be deduced from a raw 
pointer type! But as an example of some of the ideas,


<code>
     #include <iterator>
     #include <iostream>
     #include <tr1/array>
     #include <vector>

     #ifdef FOR_REAL
         template< class Type, int n >
         struct MyArray
             : std::tr1::array< Type, n >
         {};
     #else
         template< class Type, int n >
         struct MyArray
         {
             Type data;

             typedef std::iterator< std::random_access_iterator_tag, Type > 
iterator;
             iterator begin() { return iterator(); }
             Type& operator[]( int i ) { return data; }
         };
     #endif

     template< class A, class B > struct IsSameType{ enum { yes = false }; };
     template< class Type > struct IsSameType< Type, Type >{ enum { yes = true }; };

     #define STATIC_ASSERT( e ) typedef char shouldBeTrue[(e)?1:-1]
     STATIC_ASSERT(
         !(IsSameType<
             std::vector<int>::iterator,
             MyArray<int, 10>::iterator
             >::yes)
         );
     STATIC_ASSERT(
         !(IsSameType<
             int*,
             MyArray<int, 10>::iterator
             >::yes)
         );

     namespace detail {
         struct AGeneralIter {};
         struct ASpecialIter {};

         template< class Iter, class Pointee >
         struct IteratorCategory
         {
             typedef AGeneralIter    T;
         };

         // These can possibly be generated by the Boost macro repeat support. 

         template< class Pointee >
         struct IteratorCategory< typename MyArray< Pointee, 10 >::iterator, 
Pointee >
         {
             typedef ASpecialIter    T;
         };
     }    // namespace detail

     class C
     {
     private:

         template< class IterCategory, class Iter > struct Impl;

         template< class Iter >
         struct Impl< detail::AGeneralIter, Iter >
         {
             static void foo( Iter )
             {
                 std::cout << "Normal\n";
             }
         };

         template< class Iter >
         struct Impl< detail::ASpecialIter, Iter >
         {
             static void foo( Iter )
             {
                 std::cout << "Special\n";
             }
         };

     public:
         template< class Iter >
         void foo( Iter it )
         {
             typedef typename std::iterator_traits< Iter >::value_type 
Pointee;
             typedef typename detail::IteratorCategory< Iter, Pointee >::T 
Category;

             Impl< Category, Iter >::foo( it );
         }
     };

     int main()
     {
         C c;

         MyArray< int, 10 >  a1;
         c.foo( &a1[0] );        // If the code compiles, prints "Normal".
         c.foo( a1.begin() );    // If the code compiles, prints "Special".
     }
</code>


Simply define FOR_REAL to check how it fares for your tr1/array implementation.

Or, at least I hope that that's possible; naturally I haven't been able to test 
that! ;-)


Cheers, & sorry but on 2nd thought I don't think this helps with imm. prob.,

- Alf

-- 
blog at <url: http://alfps.wordpress.com>

[toc] | [prev] | [next] | [standalone]


#5224

FromRuben Safir <mrbrklyn@panix.com>
Date2011-05-20 23:33 +0000
Message-ID<ir6tni$or$1@reader1.panix.com>
In reply to#5219
mlimber <mlimber@gmail.com> wrote:
> I'm trying to overload a template member function with a dependent
> name involved. The following does not work as I'd like:
> 
> class C
> {
> public:
>   template<class Iter>
>   void Foo( Iter )
>   {
>     std::cout << "Normal\n";
>   }
> 
>   template<class T, std::size_t N>
>   void Foo( typename std::tr1::array<T,N>::iterator )
>   {
>     std::cout << "Special\n";
>   }
> };
> 
> int main()
> {
>   C c;
>   std::tr1::array<int,10> a1;
>   c.Foo( a1.begin() ); // Doesn't print "Special"!
> }
> 
> How can I get that last line in main() to invoke the special C::Foo()?

Foo is not in your class, and I'm actually surprise this compiles with
the keyword typename in the parameter list.

Ruben

[toc] | [prev] | [next] | [standalone]


#5226

From"Alf P. Steinbach /Usenet" <alf.p.steinbach+usenet@gmail.com>
Date2011-05-21 01:47 +0200
Message-ID<ir6u64$gks$1@dont-email.me>
In reply to#5224
* Ruben Safir, on 21.05.2011 01:33:
> mlimber<mlimber@gmail.com>  wrote:
>> I'm trying to overload a template member function with a dependent
>> name involved. The following does not work as I'd like:
>>
>> class C
>> {
>> public:
>>    template<class Iter>
>>    void Foo( Iter )
>>    {
>>      std::cout<<  "Normal\n";
>>    }
>>
>>    template<class T, std::size_t N>
>>    void Foo( typename std::tr1::array<T,N>::iterator )
>>    {
>>      std::cout<<  "Special\n";
>>    }
>> };
>>
>> int main()
>> {
>>    C c;
>>    std::tr1::array<int,10>  a1;
>>    c.Foo( a1.begin() ); // Doesn't print "Special"!
>> }
>>
>> How can I get that last line in main() to invoke the special C::Foo()?
>
> Foo is not in your class, and I'm actually surprise this compiles with
> the keyword typename in the parameter list.

Foo is a member of class C which is user defined. The keyword `typename` is 
needed in the parameter list. It should not compile without it.

Cheers & hth.,

- Alf

-- 
blog at <url: http://alfps.wordpress.com>

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web