未使用重载的函数:

时间:2012-02-27 17:17:56

标签: c++ templates

我有两个函数,我已经为我的调试类重载了:

  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 个答案:

答案 0 :(得分:2)

很遗憾,您的专业化没有被调用,因为您传递vector<uint8_t>::iterator而不是vector<uint8_t>::const_iterator,并且它通过模板找到完全匹配。

要修复,你要么为非const迭代器创建一个重载,要么为你的向量创建一个const-reference,并在其上调用begin() / end()

答案 1 :(得分:2)

代码中的问题是重载解析只考虑函数的参数而不考虑结果的使用方式。这意味着表达式vec.begin()(相反vec.end())只考虑vec是非常量向量,因此使用非常量版本。

虽然存在从std::vector<>::iteratorstd::vector<>::const_iterator的隐式转换,但是这种必需的转换认为重载比解析类型为std::vector<>::iterator的模板函数更糟糕。 / p>

截至解决方法,您可以为iteratorconst_iterator重载(最佳解决方案,因为解决方案仅在被调用者中),或者您可以通过强制向量为const来修复调用演员的意思:static_cast<const std::vector<uint8_T>& >(vec).begin()(这很难看,需要在所有调用中应用修复,这很难维护)

答案 2 :(得分:1)

它正在选择通用版本,因为您传递的是vector<uint8_t>::iterator而不是vector<uint8_t>::const_iterator。您应该添加第三个operator(),其中包含非const版本并将其传递给const版本。