function template problem

Discussion in 'C++' started by John Harrison, Jun 12, 2004.

  1. This might be a compiler problem or it might be some subtlety of the
    language I don't understand.

    I'm writing an iterator and I want to write a version of std::distance
    specially for my iterator. Here's some code (highly reduced of course). The
    issue is how the return type of std::distance should be written.

    #include <iostream>
    #include <cstddef>
    #include <iterator>

    template <class T>
    class Iter
    {
    public:
    typedef std::input_iterator_tag iterator_category;
    typedef T value_type;
    typedef T& reference;
    typedef T* pointer;
    typedef std::size_t size_type;
    typedef std::ptrdiff_t difference_type;
    bool operator==(Iter rhs) const { return true; }
    bool operator!=(Iter rhs) const { return false; }
    Iter& operator++() { return *this; }
    Iter operator++(int) { return *this; }
    };

    namespace std
    {
    template <class T>
    typename std::iterator_traits<Iter<T> >::distance_type /* return type 1 */
    // std::ptrdiff_t /* return type 2 */
    distance(Iter<T> first, Iter<T> last)
    {
    std::cout << "success\n";
    return 0;
    }
    }

    int main()
    {
    std::distance(Iter<int>(), Iter<int>());
    }

    On MSVC++ 7.1 this prints "success" proving that my version of std::distance
    has been called. On gcc 3.3.1 it does not. However if I change the return
    type of my version std::distance to std::ptrdiff_t, then gcc 3.3.1 prints
    "success" as well.

    I was pretty much sure this was a gcc compiler bug but I thought I'd test
    with Comeau C++ online, from what I've been able to tell Comeau works the
    same as gcc, so now I'm not so sure.

    Anyone able to tell me what's going on?

    John
     
    John Harrison, Jun 12, 2004
    #1
    1. Advertising

  2. John Harrison

    Siemel Naran Guest

    "John Harrison" <> wrote in message
    news:...

    > This might be a compiler problem or it might be some subtlety of the
    > language I don't understand.
    >
    > I'm writing an iterator and I want to write a version of std::distance
    > specially for my iterator. Here's some code (highly reduced of course).

    The
    > issue is how the return type of std::distance should be written.
    >
    > #include <iostream>
    > #include <cstddef>
    > #include <iterator>
    >
    > template <class T>
    > class Iter
    > {
    > public:
    > typedef std::input_iterator_tag iterator_category;
    > typedef T value_type;
    > typedef T& reference;
    > typedef T* pointer;
    > typedef std::size_t size_type;
    > typedef std::ptrdiff_t difference_type;
    > bool operator==(Iter rhs) const { return true; }
    > bool operator!=(Iter rhs) const { return false; }
    > Iter& operator++() { return *this; }
    > Iter operator++(int) { return *this; }
    > };
    >
    > namespace std
    > {
    > template <class T>
    > typename std::iterator_traits<Iter<T> >::distance_type /* return type 1

    */
    > // std::ptrdiff_t /* return type 2 */
    > distance(Iter<T> first, Iter<T> last)
    > {
    > std::cout << "success\n";
    > return 0;
    > }
    > }
    >
    > int main()
    > {
    > std::distance(Iter<int>(), Iter<int>());
    > }
    >
    > On MSVC++ 7.1 this prints "success" proving that my version of

    std::distance
    > has been called. On gcc 3.3.1 it does not. However if I change the return
    > type of my version std::distance to std::ptrdiff_t, then gcc 3.3.1 prints
    > "success" as well.


    MSVC 7 is right.

    As an aside, I think you can define function distance in the same namespace
    as class Iter. Koening lookup ensures that a call distance(iter1, iter2)
    finds distance in the namespace where iter1 and iter2 live, and then in the
    current namespace. But of course, people may write std::distance(...) which
    forces the use of the function in the std namespace. So what you have still
    seems a good idea.

    > I was pretty much sure this was a gcc compiler bug but I thought I'd test
    > with Comeau C++ online, from what I've been able to tell Comeau works the
    > same as gcc, so now I'm not so sure.
    >
    > Anyone able to tell me what's going on?


    There is a g++ newsgroup out there. Might be a bug.
     
    Siemel Naran, Jun 12, 2004
    #2
    1. Advertising

  3. John Harrison wrote in news: in
    comp.lang.c++:

    > This might be a compiler problem or it might be some subtlety of the
    > language I don't understand.
    >


    > typedef std::ptrdiff_t difference_type;



    > template <class T>
    > typename std::iterator_traits<Iter<T> >::distance_type /* return type


    >
    > Anyone able to tell me what's going on?
    >


    SFINAE:

    template<class T> struct iterator_traits<T*> {
    typedef ptrdiff_t difference_type;
    typedef T value_type;
    typedef T* pointer;
    typedef T& reference;
    typedef random_access_iterator_tag iterator_category;
    };

    There is no distance_type, change to difference_type.


    Rob.
    --
    http://www.victim-prime.dsl.pipex.com/
     
    Rob Williscroft, Jun 12, 2004
    #3
  4. "Rob Williscroft" <> wrote in message
    news:Xns9506693ABAC63ukcoREMOVEfreenetrtw@130.133.1.4...
    > John Harrison wrote in news: in
    > comp.lang.c++:
    >
    > > This might be a compiler problem or it might be some subtlety of the
    > > language I don't understand.
    > >

    >
    > > typedef std::ptrdiff_t difference_type;

    >
    >
    > > template <class T>
    > > typename std::iterator_traits<Iter<T> >::distance_type /* return type

    >
    > >
    > > Anyone able to tell me what's going on?
    > >

    >
    > SFINAE:
    >
    > template<class T> struct iterator_traits<T*> {
    > typedef ptrdiff_t difference_type;
    > typedef T value_type;
    > typedef T* pointer;
    > typedef T& reference;
    > typedef random_access_iterator_tag iterator_category;
    > };
    >
    > There is no distance_type, change to difference_type.
    >


    Aarrgh!! MSVC++ has distance_type for backwards compatibility.

    Thanks, and well spotted, everything works now.

    john
     
    John Harrison, Jun 12, 2004
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Robert Allan Schwartz
    Replies:
    1
    Views:
    401
    Victor Bazarov
    Aug 9, 2004
  2. Jim West
    Replies:
    3
    Views:
    774
    Jim West
    Oct 7, 2004
  3. Vijai Kalyan
    Replies:
    4
    Views:
    722
    Vijai Kalyan
    Nov 8, 2005
  4. Jeff Newman
    Replies:
    5
    Views:
    344
    Jeff Newman
    Oct 1, 2007
  5. Peng Yu
    Replies:
    3
    Views:
    790
    Thomas J. Gritzan
    Oct 26, 2008
Loading...

Share This Page