无法使用函数名称距离

时间:2013-06-03 17:15:24

标签: c++

以下代码编译良好:

#include <string>

int dist(std::string& a, std::string& b) {
  return 0;
}

int main() {
  std::string a, b;
  dist(a, b);
  return 0;
}

但是当我将函数从dist重命名为distance:

#include <string>

int distance(std::string& a, std::string& b) {
  return 0;
}

int main() {
  std::string a, b;
  distance(a, b);
  return 0;
}

编译时遇到此错误(gcc 4.2.1):

/usr/include/c++/4.2.1/bits/stl_iterator_base_types.h: In instantiation of ‘std::iterator_traits<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >’:
b.cpp:9:   instantiated from here
/usr/include/c++/4.2.1/bits/stl_iterator_base_types.h:129: error: no type named ‘iterator_category’ in ‘struct std::basic_string<char, std::char_traits<char>, std::allocator<char> >’

为什么我不能命名函数距离?

1 个答案:

答案 0 :(得分:23)

原因是存在一个名为std::distance的标准算法,它由ADL(Argument Dependent Lookup)找到:尽管您的调用不符合std命名空间,但您的参数类型{ {1}}和a(即b)与std::string函数位于同一名称空间(即std::distance),因此也会考虑std用于重载解析。

如果你真的想要调用你的函数std::distance()(我建议你不要这样做),你可以把它放在你的名字空间中,然后在调用它时完全限定函数名,或者将它保留在全局命名空间中并以这种方式调用它:

distance()

请注意,如果标准库的实现提供了 ::distance(a, b); // ^^ 的SFINAE友好版本,则单独ADL可能会导致程序编译失败(详情请参阅{{} 3}} - 由this Q&A on StackOverflow提供。

对于iterator_traits的SFINAE友好实现,您的编译器应该认识到iterator_traits函数模板(因为它是模板)在给定类型std::distance()的参数时无法实例化,因为它的返回类型:

std::string

在这种情况下,编译器只是为了重载解析而丢弃此模板并选择template< class InputIt > typename std::iterator_traits<InputIt>::difference_type // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // Trying to instantiate this with InputIt = std::string // may result in a soft error during type deduction if // your implementation is SFINAE-friendly, and in a hard // error otherwise. distance( InputIt first, InputIt last ); 函数。

但是,如果您的标准库实现不提供SFINAE友好版本的distance(),则替换失败可能发生在不符合SFINAE条件的上下文中,从而导致(硬)编译错误

MooingDuck显示您的原始程序使用GCC 4.8.0进行编译,该程序附带了一个版本的libstdc ++,它实现了对SFINAE友好的iterator_traits