c++visual-studio-2019

Return a std::set with a custom comparator


I'm trying to write a function to return a std::set with a custom comparator (per the advice from this answer), as follows:

#include <iostream>
#include <set>

auto GetSet()
{
    const auto cmp = [](auto n1, auto n2) { return n1 < n2; };
    std::set<int, decltype(cmp)> mySet(cmp); // compiler error, see below
    mySet.insert(13);
    mySet.insert(31);
    return mySet;
}
int main()
{
    auto mySet = GetSet();
    for (auto i : mySet)
        std::cout << i << " ";
}

Obviously this is for demonstration purposes, my class is more complex than an int

It works fine in GCC Coliru link, but does not work in VS2019. In VS2019 (using /std:c++17) it produces the following error:

Error C2783 'void std::swap(_Ty &,_Ty &) noexcept()': could not deduce template argument for '_Enabled' C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\utility 114

If I change the code to not use the function, and instead have:

int main()
{
    const auto cmp = [](auto n1, auto n2) { return n1 < n2; };
    std::set<int, decltype(cmp)> mySet(cmp);
    mySet.insert(13);
    mySet.insert(31);
    for (auto i : mySet)
        std::cout << i << " ";
}

It works correctly. Is there anything wrong with the above, or is Microsoft being more pedantic, or some kind of compiler bug?


Solution

  • This appears to just be a bug in VS19, as I'm now using VS22 and the code in the question works fine.

    For anyone experiencing the same issue, it's possible to workaround it by explicitly declaring the type of cmp as std::function<bool(int, int)> as below:

    #include <set>
    #include <functional>
    auto GetSet()
    {
        const auto cmp = [](auto n1, auto n2) { return n1 < n2; };
        std::set<int, std::function<bool(int, int)>> mySet(cmp);
        mySet.insert(13);
        mySet.insert(31);
        return mySet;
    }
    

    This works on GCC, VS19 and VS22