1

I want to make a decreasing string sort in a set using lambda expression, but I don't know why I've got this error: "error C3497: you cannot construct an instance of a lambda". Can anyone help me, please.

#include <set>
#include <iostream>
#include <iterator>
#include <string>
#include <functional>

using namespace std;
typedef set<string, greater<string> > DecreasingStringSet;

int main()
{
    //lambda expression
    auto comp = [](string x, string y){ return x > y; };
    set< string , decltype(comp) > s(comp);
    s.insert("one");
    s.insert("two");
    s.insert("three");
    s.insert("four");
    for (auto x : s){
        cout << x << " ";
    }
    cout << endl;
    return 0;
}
kaan_93
  • 85
  • 1
  • 10
  • What compiler are you using? It works here: http://ideone.com/HKMuuI for me. – yizzlez May 15 '14 at 21:18
  • The type of a lambda is unspecified (Ok, its only a functor generated by the compiler, but its a unspecified functor) so expressions like `decltype(lambda)` are not possible. – Manu343726 May 15 '14 at 21:19
  • I use compiler from visual studio 2012 – kaan_93 May 15 '14 at 21:20
  • I get that error under VS2013, too. It works under GCC 4.7 though, for some reason. – Rook May 15 '14 at 21:21
  • 2
    It is a reported bug http://connect.microsoft.com/VisualStudio/feedback/details/727957/vc11-beta-compiler-fails-to-compile-lambda-key-comparer-for-maps-and-sets , they told: "... we may not have time to fix it in VC12 ..." – carlosvin May 15 '14 at 21:27
  • Actually, this is quite obviously not a dupe of that, because it's actually about creating a string set in decreasing order, not as much about using a lambda as comparator. – sehe May 15 '14 at 21:29
  • Definitively this is a dup: Google "C++11 decltype() lambda" returns [this](http://stackoverflow.com/questions/13631890/use-decltype-and-stdfunction-with-lambda), which is exactly the same question (And the same answer provided by Rook) – Manu343726 May 15 '14 at 21:30
  • @Manu343726 well, that's ignoring "I want to make a decreasing string sort in a set", the fact that the code already contains `typedef set > DecreasingStringSet;` and the fact that this solution is quite clearly superior in this particular situation. I strive to answer the essence of a question too – sehe May 15 '14 at 21:33

2 Answers2

1

As mentioned by Manu above, the type of a lambda is unspecified. However, you can wrap it up in a std::function:

set< string, std::function<int(string x, string y)>> s(comp);

Incidentally, this sort of sorting predicate should 1) have const parameters (because you shouldn't be modifying the items being sorted during that sort) and 2) should be ref parameters if they're objects... as normal value parameters you'll be doing an awful lot of unnecessary copying, which will make thing inefficient.

Use this instead:

auto comp = [](const string&  x, const string&  y){ return x > y; };
set< string, std::function<int(const string& x, const string&  y)>> s(comp);
Rook
  • 5,734
  • 3
  • 34
  • 43
  • Alright, that's it, thank you. And yeah, on GCC is working fine, thank you too. – kaan_93 May 15 '14 at 21:25
  • @user3456848 *"Alright, that's it, thank you. And yeah, on GCC is working fine, thank you too"* So why not accept the answer? – Manu343726 May 15 '14 at 21:31
0

You already had the solution:

using namespace std;
typedef set<string, greater<string> > DecreasingStringSet;

int main()
{
    DecreasingStringSet s;

That's it. See it Live ON Coliru

It will be a lot more efficient than the lambda/std::function<> approach, plus it results in a class that is default constructible.

yizzlez
  • 8,757
  • 4
  • 29
  • 44
sehe
  • 374,641
  • 47
  • 450
  • 633