Search code examples
stringsortingc++17c++20stdvector

Why sorting a vector of strings with generic lambda doesn't work?


#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

bool sortByName(const auto& first, const auto& second) {
    return first < second;
}

void print(const auto& vec) {
    for(const auto& s : vec)
    cout << s << ", ";
    cout << endl;
}

int main() {
    vector vec2 = {"sam", "zach", "adam", "peter"};
    print(vec2);

    auto cmp = [](const auto& s1, const auto& s2) {
        return s1 < s2;
    };
    std::sort(vec2.begin(), vec2.end(), cmp);          // line (1)
    print(vec2);

    auto cmp2 = [](const string& s1, const string& s2) {
        return s1 < s2;
    };
    std::sort(vec2.begin(), vec2.end(), cmp2);         // line (2)
    print(vec2);
}

For the above code snippet, the results are as below,

  1. std::sort with cmp2 sorts the vector i.e. {adam, peter, sam, zach,}
  2. std::sort with cmp keeps the elements of vector in same order, as the original vector i.e. {sam, zach, adam, peter,}

Why do we have to explicitly provide the type i.e. "string" in cmp2 to make this sort work?


Solution

  • vector vec2 = {"sam", "zach", "adam", "peter"};
    

    This makes vec2 into a std::vector<const char*>.

    You are therefore comparing const char* in the generic lambda and not what the pointers are actually pointing at.

    In order to make it work without converting the const char*s to std::strings (or better, std::string_views), you could use std::strcmp:

    #include <cstring>
    
    auto cmp = [](const char* s1, const char* s2) {
        return std::strcmp(s1, s2) < 0;
    };