* 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>