G++ Bug in finding template instanciation

kanze@gabi-soft.de kanze@gabi-soft.de
Sun May 7 13:39:00 GMT 2000


The attached source doesn't compile, at least under Windows.
Apparently, the compiler is having trouble finding the template
function which takes the references to the nested class; unnest Iter,
and it works.

Compiler output:

-----------------------------------------------------------------------------
> g++ -v copytest.cc -o copytest
Reading specs from /Program/Cygnus/cygwin-b20/H-i586-cygwin32/bin/../lib/gcc-lib/i586-cygwin32/2.95/specs
gcc version 2.95 19990728 (release)
 /Program/Cygnus/cygwin-b20/H-i586-cygwin32/bin/../lib/gcc-lib/i586-cygwin32/2.95/cpp.exe -lang-c++ -v -iprefix /Program/Cygnus/cygwin-b20/H-i586-cygwin32/bin/../lib/gcc-lib/i586-cygwin32/2.95/ -D__GNUC__=2 -D__GNUG__=2 -D__GNUC_MINOR__=95 -D__cplusplus -Di386 -D_WIN32 -DWINNT -D_X86_=1 -D__STDC__=1 -D__stdcall=__attribute__((__stdcall__)) -D__cdecl=__attribute__((__cdecl__)) -D__declspec(x)=__attribute__((x)) -D__i386__ -D_WIN32 -D__WINNT__ -D_X86_=1 -D__STDC__=1 -D__stdcall=__attribute__((__stdcall__)) -D__cdecl=__attribute__((__cdecl__)) -D__declspec(x)=__attribute__((x)) -D__i386 -D__WINNT -Asystem(winnt) -Acpu(i386) -Amachine(i386) -D__EXCEPTIONS -remap -Acpu(i386) -Amachine(i386) -Di386 -D__i386 -D__i386__ -Di586 -Dpentium -D__i586 -D__i586__ -D__pentium -D__pentium__ -D__CYGWIN32__ -D__CYGWIN__ copytest.cc c:\tmp/ccWtcaaa.ii
GNU CPP version 2.95 19990728 (release) (80386, BSD syntax)
#include "..." search starts here:
#include <...> search starts here:
 /Program/Cygnus/cygwin-b20/H-i586-cygwin32/bin/../lib/gcc-lib/i586-cygwin32/2.95/../../../../../include/g++-3
 /Program/Cygnus/cygwin-b20/H-i586-cygwin32/bin/../lib/gcc-lib/i586-cygwin32/2.95/../../../../../include
 /Program/Cygnus/cygwin-b20/H-i586-cygwin32/bin/../lib/gcc-lib/i586-cygwin32/2.95/../../../../i586-cygwin32/include
 /Program/Cygnus/cygwin-b20/H-i586-cygwin32/bin/../lib/gcc-lib/i586-cygwin32/2.95/include
End of search list.
The following default directories have been omitted from the search path:
 /usr/include
End of omitted list.
 /Program/Cygnus/cygwin-b20/H-i586-cygwin32/bin/../lib/gcc-lib/i586-cygwin32/2.95/cc1plus.exe c:\tmp/ccWtcaaa.ii -quiet -dumpbase copytest.cc -version -o c:\tmp/ccINeaaa.s
GNU C++ version 2.95 19990728 (release) (i586-cygwin32) compiled by GNU C version 2.95 19990728 (release).
/Program/Cygnus/cygwin-b20/H-i586-cygwin32/bin/../lib/gcc-lib/i586-cygwin32/2.95/../../../../../include/g++-3/stl_algobase.h: In function `class basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > * __copy<Wrapper<basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > >::Iter, basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > *, ptrdiff_t>(Wrapper<basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > >::Iter, Wrapper<basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > >::Iter, basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > *, random_access_iterator_tag, ptrdiff_t *)':
/Program/Cygnus/cygwin-b20/H-i586-cygwin32/bin/../lib/gcc-lib/i586-cygwin32/2.95/../../../../../include/g++-3/stl_algobase.h:161:   instantiated from `__copy_dispatch<Wrapper<basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > >::Iter,basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > *,__false_type>::copy(Wrapper<basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > >::Iter, Wrapper<basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > >::Iter, basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > *)'
/Program/Cygnus/cygwin-b20/H-i586-cygwin32/bin/../lib/gcc-lib/i586-cygwin32/2.95/../../../../../include/g++-3/stl_algobase.h:188:   instantiated from `copy<Wrapper<basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > >::Iter, basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > *>(Wrapper<basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > >::Iter, Wrapper<basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > >::Iter, basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > *)'
copytest.cc:175:   instantiated from here
/Program/Cygnus/cygwin-b20/H-i586-cygwin32/bin/../lib/gcc-lib/i586-cygwin32/2.95/../../../../../include/g++-3/stl_algobase.h:138: no match for `Wrapper<basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > >::Iter & - Wrapper<basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> > >::Iter &'
-----------------------------------------------------------------------------

Source.  Sorry if it is so long, but I don't want to take the risk of
doing anything to make the iterator invalid.  It's mostly pretty
trivial.  As mentioned above, if Iter is a separate template, not part
of Wrapper, it compiles and works as expected.

-----------------------------------------------------------------------------

#include <algorithm>
#include <iterator>
#include <string>
#include <stddef.h>

template< typename T >
class Wrapper
{
public:
    class Iter
    {
    public:
        typedef T const     value_type ;
        typedef ptrdiff_t   difference_type ;
        typedef T const*    pointer ;
        typedef T const&    reference ;
        typedef std::random_access_iterator_tag
                            iterator_category ;

        explicit            Iter( T const* a , int n ) ;

        T const&            operator*() const ;
        T const*            operator->() const ;
        T const&            operator[]( ptrdiff_t index ) const ;

        Iter&               operator++() ;
        Iter                operator++( int ) ;
        Iter&               operator+=( ptrdiff_t offset ) ;
        Iter&               operator--() ;
        Iter                operator--( int ) ;
        Iter&               operator-=( ptrdiff_t offset ) ;

        int                 compare( Iter const& other ) const ;
    private:
        T const*            array ;
        ptrdiff_t           index ;
    } ;

                        Wrapper( T const* array , int length ) ;
    Iter                begin() const ;
    Iter                end() const ;

private:
    T const*            myArray ;
    int                 myLength ;
} ;

template< typename T >
Wrapper<T>::Iter::Iter( T const* a , int n )
    :   array( a )
    ,   index( n )
{
}

template< typename T >
T const&
Wrapper<T>::Iter::operator*() const
{
    return array[ index ] ;
}

template< typename T >
T const*
Wrapper<T>::Iter::operator->() const
{
    return &array[ index ] ;
}

template< typename T >
T const&
Wrapper<T>::Iter::operator[]( ptrdiff_t index ) const
{
    return array[ index ] ;
}

template< typename T >
Wrapper<T>::Iter&
Wrapper<T>::Iter::operator++()
{
    ++ index ;
    return *this ;
}

template< typename T >
Wrapper<T>::Iter
Wrapper<T>::Iter::operator++( int )
{
    Wrapper<T>::Iter             result( *this ) ;
    operator++() ;
    return result ;
}

template< typename T >
Wrapper<T>::Iter&
Wrapper<T>::Iter::operator+=( int offset )
{
    index += offset ;
    return *this ;
}

template< typename T >
Wrapper<T>::Iter&
Wrapper<T>::Iter::operator--()
{
    -- index ;
    return *this ;
}

template< typename T >
Wrapper<T>::Iter
Wrapper<T>::Iter::operator--( int )
{
    Wrapper<T>::Iter                result( *this ) ;
    operator--() ;
    return result ;
}

template< typename T >
Wrapper<T>::Iter&
Wrapper<T>::Iter::operator-=( int offset )
{
    index -= offset ;
    return *this ;
}


template< typename T >
int
Wrapper<T>::Iter::compare( Wrapper<T>::Iter const& other ) const
{
    return index == other.index
        ?   true
        :   index > other.index
        ?   1
        :   -1 ;
}

template< typename T >
ptrdiff_t
operator-( Wrapper<T>::Iter const& op1 , Wrapper<T>::Iter const& op2 )
{
    return 5 ;
}

template< typename T >
Wrapper< T >::Wrapper( T const* array , int length )
    :   myArray( array )
    ,   myLength( length )
{
}

template< typename T >
Wrapper< T >::Iter
Wrapper< T >::begin() const
{
    return Iter( myArray , 0 ) ;
}

template< typename T >
Wrapper< T >::Iter
Wrapper< T >::end() const
{
    return Iter( myArray , 5 ) ;
}


int
main()
{
    std::string         init[] = { "1" , "2" , "3" , "4" , "5" } ;
    Wrapper< std::string >
                        src( init , 5 ) ;
    std::string         dst[ 5 ] ;
    std::copy( src.begin() , src.end() , dst ) ;
    for ( int i = 0 ; i < 5 ; ++ i ) {
        cout << dst[ i ] << '\n' ;
    }
    return 0 ;
}
-----------------------------------------------------------------------------

--
James Kanze                               mailto:kanze@gabi-soft.de
Conseils en informatique orientée objet/
                   Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


More information about the Gcc-bugs mailing list