error c2373 redefinition different type modifiers with a template class

Viewed 345

I wrote a template Interval class that I would like to use as a container for an interval of numbers. Since I would like to iterate over the elements virtually contained in this class, I added a template ItervalIter friend class to the mix.

When I compile the project on Linux with gcc and on MacOS with clang, everything compiles fine without warnings. When I compile on Windows with msvc, I get the following error message:

C2373 'utils::Interval<T>::begin': redefinition. The type modifiers are different
C2447 '{': missing function header (old-style formal list?)
C2373 'utils::Interval<T>::end': redefinition. The type modifiers are different
C2447 '{': missing function header (old-style formal list?)

I have simplified my implementation of the Interval class so as to obtain the following MRE:

interval.h

#pragma once
#ifndef INTERVAL_H_INCLUDED
#define INTERVAL_H_INCLUDED

namespace utils {

    template <class T> class IntervalIter;

    //-----------------------------------------------------------------------------
    // Interval
    //-----------------------------------------------------------------------------

    template <class T>
    class Interval {
    public:
        Interval();
        Interval(const T value);
        virtual ~Interval();

        ///< iterator
        friend class IntervalIter<T>;
        typedef IntervalIter<T> iterator;
        typedef const IntervalIter<T> const_iterator;
        iterator begin();
        iterator end();
        const_iterator begin() const;
        const_iterator end() const;

    private:
        T value_;
    };

//-----------------------------------------------------------------------------
// IntervalIter
//-----------------------------------------------------------------------------

    template <class T>
    class IntervalIter {
    public:
        IntervalIter(T cur) : _cur(cur) {};

    private:
        T _cur;
    };

//-----------------------------------------------------------------------------
// Interval -- Impl.
//-----------------------------------------------------------------------------


    template <class T>
    Interval<T>::Interval(const T value)
        : value_(value)
    {
        // nothing to do
    }

    template <class T>
    Interval<T>::~Interval()
    {
        // nothing to do
    }

    template <class T>
    typename Interval<T>::iterator Interval<T>::begin()
    {
        return this->value_;
    }

    template <class T>
    typename Interval<T>::iterator Interval<T>::end()
    {
        return this->value_;
    }

    template <class T>
    typename Interval<T>::const_iterator Interval<T>::begin() const
    {
        return const_cast<Interval<T>*>(this)->begin();
    }

    template <class T>
    typename Interval<T>::const_iterator Interval<T>::end() const
    {
        return const_cast<Interval<T>*>(this)->end();
    }


} // namespace utils
#endif
#pragma once

main.cpp

#include "interval.h"

template class utils::Interval<int>;

int main(int argc, char* argv[])
{
    utils::Interval<int> values(10);
}

The problem appears to be here:

    template <class T>
    typename Interval<T>::const_iterator Interval<T>::begin() const
    {
        return const_cast<Interval<T>*>(this)->begin();
    }

    template <class T>
    typename Interval<T>::const_iterator Interval<T>::end() const
    {
        return const_cast<Interval<T>*>(this)->end();
    }

rewriting it as follows gets rid of the error:

    template <class T>
    typename const IntervalIter<T> Interval<T>::begin() const
    {
        return const_cast<Interval<T>*>(this)->begin();
    }

    template <class T>
    typename const IntervalIter<T> Interval<T>::end() const
    {
        return const_cast<Interval<T>*>(this)->end();
    }

Q:

  • what is going on? did I define const_iterator incorrectly?
  • is there a better solution than the one I have found?

NOTE: I forgot to mention that I am stuck with all and only the C++ features available before stdc++11.

0 Answers
Related