distance calculation error in c++ [closed]

不羁的心 提交于 2019-11-29 05:22:48

This is caused in part by your use of using namespace std;.

There is a function in the standard library, std::distance, that is used to compute the distance between two iterators into a container. That function is being selected during overload resolution instead of your distance function.

If you don't use using namespace std;, you won't have this problem. Your use of using namespace std; brings all of the names from the std namespace into the global namespace. This is bad because there are a lot of common names in namespace std and it can cause convoluted issues during name lookup, as you've discovered here.

In general, prefer not to use using namespace, especially not at file scope. It's far easier and clearer in the long run to qualify each of the names that you want to use.

@James is right in that getting rid of using namespace std will make this problem go away. But that's not exactly what the actual problem is.

The problem comes from the way names are resolved in C++. C++ uses a very aggressive approach to resolving name lookups when resolving the names of free functions if no suitable class member was found. This is called Argument-dependent name lookup (or ADL), sometimes referred to as Koenig lookup. And at the same time, it is one of the things makes C++ so powerful, but also so deadly and confounding.

Here's the basic problem, simplified.

You call vector::operator[] which returns a vector::reference or a vector::const_reference. You take this return value and call distance() unqualified.

Because distance wasn't found in and applicable class, ADL kicks in, which goes out and gets too many potential matching names.

ADL then goes through the list of candidates and picks "the best match". In this case, the reference that operator[] returns is a closer match to the type expected by std::distance than by your distance, although both are compatible, so std::distance is selected.

Several ways to solve this problem:

  1. Don't using namespace std. Instead, using just the peices you want.
  2. Quantify explicitly which distance you refer to using the scope resolution operator: ::distance()
  3. Change distance to take pointers instead of const &. This effectively turns off ADL.:

Example:

int distance(const Point* a,const Point* b)
s+=square(distance(&a[0],&a[1]));

Additional Resources:

"A Modest Proposal: Fixing ADL (revision 2)" by Herb Sutter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!