Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #5219 > unrolled thread
| Started by | mlimber <mlimber@gmail.com> |
|---|---|
| First post | 2011-05-20 13:37 -0700 |
| Last post | 2011-05-21 01:47 +0200 |
| Articles | 7 — 3 participants |
Back to article view | Back to comp.lang.c++
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
| From | mlimber <mlimber@gmail.com> |
|---|---|
| Date | 2011-05-20 13:37 -0700 |
| Subject | Overloading 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]
| From | mlimber <mlimber@gmail.com> |
|---|---|
| Date | 2011-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]
| From | "Alf P. Steinbach /Usenet" <alf.p.steinbach+usenet@gmail.com> |
|---|---|
| Date | 2011-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]
| From | mlimber <mlimber@gmail.com> |
|---|---|
| Date | 2011-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]
| From | "Alf P. Steinbach /Usenet" <alf.p.steinbach+usenet@gmail.com> |
|---|---|
| Date | 2011-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]
| From | Ruben Safir <mrbrklyn@panix.com> |
|---|---|
| Date | 2011-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]
| From | "Alf P. Steinbach /Usenet" <alf.p.steinbach+usenet@gmail.com> |
|---|---|
| Date | 2011-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