Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Overloading a template member function with a dependent name

Reply
Thread Tools

Overloading a template member function with a dependent name

 
 
mlimber
Guest
Posts: n/a
 
      05-20-2011
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()?
 
Reply With Quote
 
 
 
 
mlimber
Guest
Posts: n/a
 
      05-20-2011
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
 
Reply With Quote
 
 
 
 
mlimber
Guest
Posts: n/a
 
      05-20-2011
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
 
Reply With Quote
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      05-20-2011
* 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>
 
Reply With Quote
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      05-20-2011
* 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>
 
Reply With Quote
 
Ruben Safir
Guest
Posts: n/a
 
      05-20-2011
mlimber <> 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
 
Reply With Quote
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      05-20-2011
* Ruben Safir, on 21.05.2011 01:33:
> mlimber<> 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>
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
overloading non-template member functions with template member functions Hicham Mouline C++ 1 04-24-2009 07:47 AM
overloading non-template member functions with template member functions Hicham Mouline C++ 0 04-23-2009 11:42 AM
non-dependent vs. dependent template names puzzlecracker C++ 1 08-07-2008 07:42 AM
non-dependent name in template function George2 C++ 0 03-10-2008 02:10 AM
parse error in gcc but success in vc.net, call a non_template class's template member function from a template class's member function! ken C++ 2 06-28-2005 06:57 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57