ADL. Кто неправ я, компилятор или реализация STL
От: Kazmerchuk Pavel  
Дата: 20.10.06 19:39
Оценка:
В моей библиотеке при переходе на версию STL из поставки VS2005 (с STLPort все в порядке)
полезли ошибки компиляции. Вот минимальный код, приводящий к ошибке

#include "stdafx.h"
#include <vector>

namespace mtr{

  template<typename T>
  class Argument
  {
    const T& arg_;   

  public:

    Argument(T const& arg) 
      : arg_(arg) 
    {}
  };

  template<typename T, typename U>
  class Expression
  {
    typedef Argument<T> Left;
    typedef Argument<U> Right;

    const Left  left_;
    const Right right_;  

  public:

    Expression( const Left& left, const Right& right )
      : left_(left), right_(right) 
    {}
  };

  struct Matrix
  {
    float p[3];
  };

  template<typename Left, typename Right>
  inline Expression<Left, Right> operator + (Left const& a, Right const& b )
  {
    return Expression<Left, Right>(a, b);
  }
}

int _tmain(int argc, _TCHAR* argv[])
{
  std::vector<mtr::Matrix> v;
  v.resize(2);
  
  return 0;
}


Ошибка компиляции в недрах std::vector<>::resize, которая определена так:
void resize(size_type _Newsize, _Ty _Val)
{
  if (size() < _Newsize)
    _Insert_n(end(), _Newsize - size(), _Val);
  else if (_Newsize < size())
    erase(begin() + _Newsize, end());
}

Проблема в выражении begin() + _Newsize и заключается в том, что _Newsize имеет тип size_type, а для итератора, возаращаемого begin() операция сложения определена так:
_Myt operator+(difference_type _Off) const
{  // return this + integer
  _Myt _Tmp = *this;
  return (_Tmp += _Off);
}

Что делает компилятор: он считает, что вместо преобразования size_type->difference_type [это преобразование unsigned int->int для того чтобы
вызвать operator+(difference_type _Off) const ] более подходящим являетя мой шаблонный!! оператор Expression<Left, Right> operator + (Left const& a, Right const& b ),
который он и подставляет. Дальше все по плану: Expression<Left, Right> не возможно превести к std::vector<>::iterator, который требуется для вызова erase(...)

Вопрос 1. Почему компилятор лезет в мое пространство имен, проводя зависимый поиск, хотя аргументы в begin() + _Newsize к нему ни какого отношения не имеют?
Вопрос 2. Почему если внутри resize (для вызова begin() + _Newsize) требуется приведение типа разработчики на сделали это явно (это конечно если компилятор прав в первом вопросе)?
Вопрос 3. Что делать? Править исходник вектора не хочется.

ps: с STLPort все в порядке потому, что в векторе итератор это просто голый указатель. С ним у компилятора вопросов не возникает.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.