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_iteratorincorrectly? - 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.