Перегруженная функция не используется: - PullRequest
2 голосов
/ 27 февраля 2012

У меня есть две функции, которые я перегрузил для моего класса отладки:

  template<class IteratorT>
    inline debug&
    operator()(const std::string& name,
               IteratorT begin,
               IteratorT end)
    {
      _stream << indent(internal) << "g< " << name << " : [ ";
      for (auto i = begin; i != end; i++)
        _stream << (*i) << " ";
      _stream << "] >" << std::endl;

      return *this;
    }

И

  inline debug&
  operator()(const std::string& name,
             std::vector<uint8_t>::const_iterator begin,
             std::vector<uint8_t>::const_iterator end)
  {
    _stream << indent(internal) << "u8< " << name << " : [ " << std::hex;
    std::copy(begin, end, std::ostream_iterator<uint32_t>(_stream, " "));
    _stream << "] >" << std::endl;

    return *this;
  }

Вот фрагмент кода его использования:

int main()
{
  debug log;

  std::vector<uint8_t> vec;
  vec.push_back(0xde);
  vec.push_back(0xad);
  vec.push_back(0xc0);
  vec.push_back(0xde);

  log("vec", vec.begin(), vec.end());
}

Вывод (поскольку он не печатается в виде шестнадцатеричных символов, я пропустил неформатированный результат):

g< "vec" : [ ... ] >

Вместо

u8< "vec" : [ de ad c0 de ] >

По какой-то причине компилятор невыбор правильной, перегруженной функции.

$ g++47 --version
g++47 (GCC) 4.7.0 20120224 (experimental)

Ответы [ 3 ]

2 голосов
/ 27 февраля 2012

Проблема в коде заключается в том, что разрешение перегрузки учитывает только аргументы функции, а не то, как будет использоваться результат. Это означает, что выражение vec.begin() (наоборот vec.end()) учитывает только то, что vec является неконстантным вектором, и поэтому оно использует неконстантную версию.

Хотя существует неявное преобразование из std::vector<>::iterator в std::vector<>::const_iterator, это требуемое преобразование считает перегрузку худшим кандидатом на разрешение, чем функция шаблона с заменой типа std::vector<>::iterator.

Начиная с обходных путей, вы можете перегружать как iterator, так и const_iterator (лучшее решение, поскольку решение находится только в вызываемом абоненте), или вы можете исправить вызовы, заставив вектор быть константным с помощью приведения. : static_cast<const std::vector<uint8_T>& >(vec).begin() (что некрасиво и требует применения исправления во всех вызовах, которое сложно поддерживать)

2 голосов
/ 27 февраля 2012

К сожалению, ваша специализация не вызывается, потому что вы передаете vector<uint8_t>::iterator, а не vector<uint8_t>::const_iterator, и она находит точное соответствие через шаблон.

Чтобы исправить, вы либо создаете перегрузку также для неконстантных итераторов, либо создаете const-ссылку на свой вектор и вызываете begin() / end() для этого.

1 голос
/ 27 февраля 2012

Он выбирает общую версию, потому что вы передаете vector<uint8_t>::iterator, а не vector<uint8_t>::const_iterator. Вы должны добавить третью operator(), которая принимает версию, отличную от const, и передает ее const.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...