3

I have encountered a situation where a call to std::sort() works without explicitly writing the namespace. According to Using std::sort() without prefix "std" and also without "using namespace std;" compiles successfully, the compiler uses ADL and considers the namespaces of the arguments. Since vector is in std, it finds std::sort.

In the following program, ADL fails for the second call to sort when using Visual Studio 2010. Since the iterators are the same, std::sort should be findable. But the compiler says C3861 'identifier': identifier not found. Why?

#include <algorithm>
#include <vector>

class StableSortClass
{
public:
  int m_i;
};

bool lessStableSortClass(const StableSortClass & lhs, const StableSortClass & rhs) {return lhs.m_i < rhs.m_i;}

int main(int argc, char **argv)
{
  std::vector<StableSortClass> vec;

  // works because of ADL without std::
  sort(vec.begin(), vec.end(), lessStableSortClass);
  
  // does not compile in Visual Studio 2010
  sort(vec.begin(), vec.end(), [](const StableSortClass & lhs, const StableSortClass & rhs) {return lhs.m_i < rhs.m_i;});

  // compiles
  std::sort(vec.begin(), vec.end(), [](const StableSortClass & lhs, const StableSortClass & rhs) {return lhs.m_i < rhs.m_i;});

  return 0;
}

EDIT

To answer the comments so far:

  1. I don't want to rely on ADL. I found code in a header and wondered why the compiler does not complain to the missing std::. I then noticed that the std:: is sometimes required and sometimes not, hence this question.
  2. C3861 'identifier': identifier not found is the complete error message the compiler gave to me. Nothing more.
  3. Yes, some folks do maintenance for old production systems where VS2010 is used. It could be worse ;-)
Fabian
  • 4,001
  • 4
  • 28
  • 59
  • Why are you using the VC++ 2010 compiler? – Dai Feb 01 '23 at 08:25
  • 2
    The support for C++11 in VS *2010* should be expected to be a bit spotty. – molbdnilo Feb 01 '23 at 08:27
  • 2
    Also, never rely on ADL when the relevant arguments are iterators - they could suddenly be raw pointers if you change compiler or even just compile flags. (Some libraries have custom vector iterator classes in debug mode, but raw pointers in release.) – Sebastian Redl Feb 01 '23 at 08:31
  • I expect the complete error message to tell more. Always read the complete error message, `C3861 'identifier': identifier not found` is only the generic part which isnt very useful – 463035818_is_not_an_ai Feb 01 '23 at 08:40
  • btw in some sense `std::sort` has ADL enabled only by coincidence. If you wanted to call a different sorting method, you'd just call it rather than rely on ADL. – 463035818_is_not_an_ai Feb 01 '23 at 08:42
  • @SebastianRedl I think this advice is good only for containers with continuous memory, so: std::vector, std::basic_string, std::initializer_list std::array c-array and views on those containers: std::basic_string_view std::span – Marek R Feb 01 '23 at 12:26
  • @MarekR That's already a lot. And I think it's good advice in general to not rely on ADL when you don't control the argument types exactly. – Sebastian Redl Feb 01 '23 at 12:42
  • There is also `std::ranges::sort` which can't work with ADL (extra level of namespace), at least `begin` `end` becomes obsolete. Also `projection` feature is quite cool (even for example from question). – Marek R Feb 01 '23 at 13:04
  • Your 2 `sort` should compile/not compile the same way with ADL on the iterators. – Jarod42 Feb 01 '23 at 14:00
  • *"is the complete error message the compiler gave to me. Nothing more."* There are several panes: "Errors list" which is a resume, and "Build Output" which might have additional information. – Jarod42 Feb 01 '23 at 14:02
  • @Jarod42 I checked those places. It baffles me too that the output is so terse. – Fabian Feb 23 '23 at 06:35

0 Answers0