0

I have a struct:

struct some_struct {
    int i;
    char c;
};

Now I want to put it in a std::set using a custom compare function:

set<some_struct*, bool(*)(some_struct* s1, some_struct* s2)> s_s(
    [](some_struct* s1, some_struct* s2)->bool {return s1->i < s2->i;}
);

Everything works well so far. However, for some weird reason I can't put anything in the lambda's capture list:

int sgn=-1;
set<some_struct*, bool(*)(some_struct* s1, some_struct* s2)> s_s(
    [sgn](some_struct* s1, some_struct* s2)->bool {return sgn*s1->i < sgn*s2->i;}
);

The above code produces a rather lengthy compilation error (ideone):

prog.cpp: In function ‘int main()’:
prog.cpp:14:2: error: no matching function for call to ‘std::set<some_struct*, bool (*)(some_struct*, some_struct*)>::set(main()::<lambda(some_struct*, some_struct*)>)’
  );
  ^
In file included from /usr/include/c++/6/set:61:0,
                 from prog.cpp:1:
/usr/include/c++/6/bits/stl_set.h:252:9: note: candidate: template<class _InputIterator> std::set<_Key, _Compare, _Alloc>::set(_InputIterator, _InputIterator, const allocator_type&)
         set(_InputIterator __first, _InputIterator __last,
         ^~~
/usr/include/c++/6/bits/stl_set.h:252:9: note:   template argument deduction/substitution failed:
prog.cpp:14:2: note:   candidate expects 3 arguments, 1 provided
  );
  ^
In file included from /usr/include/c++/6/set:61:0,
                 from prog.cpp:1:
/usr/include/c++/6/bits/stl_set.h:246:7: note: candidate: std::set<_Key, _Compare, _Alloc>::set(std::initializer_list<_Tp>, const allocator_type&) [with _Key = some_struct*; _Compare = bool (*)(some_struct*, some_struct*); _Alloc = std::allocator<some_struct*>; std::set<_Key, _Compare, _Alloc>::allocator_type = std::allocator<some_struct*>]
       set(initializer_list<value_type> __l, const allocator_type& __a)
       ^~~
/usr/include/c++/6/bits/stl_set.h:246:7: note:   candidate expects 2 arguments, 1 provided
/usr/include/c++/6/bits/stl_set.h:240:7: note: candidate: std::set<_Key, _Compare, _Alloc>::set(std::set<_Key, _Compare, _Alloc>&&, const allocator_type&) [with _Key = some_struct*; _Compare = bool (*)(some_struct*, some_struct*); _Alloc = std::allocator<some_struct*>; std::set<_Key, _Compare, _Alloc>::allocator_type = std::allocator<some_struct*>]
       set(set&& __x, const allocator_type& __a)
       ^~~
/usr/include/c++/6/bits/stl_set.h:240:7: note:   candidate expects 2 arguments, 1 provided
/usr/include/c++/6/bits/stl_set.h:236:7: note: candidate: std::set<_Key, _Compare, _Alloc>::set(const std::set<_Key, _Compare, _Alloc>&, const allocator_type&) [with _Key = some_struct*; _Compare = bool (*)(some_struct*, some_struct*); _Alloc = std::allocator<some_struct*>; std::set<_Key, _Compare, _Alloc>::allocator_type = std::allocator<some_struct*>]
       set(const set& __x, const allocator_type& __a)
       ^~~
/usr/include/c++/6/bits/stl_set.h:236:7: note:   candidate expects 2 arguments, 1 provided
/usr/include/c++/6/bits/stl_set.h:232:7: note: candidate: std::set<_Key, _Compare, _Alloc>::set(const allocator_type&) [with _Key = some_struct*; _Compare = bool (*)(some_struct*, some_struct*); _Alloc = std::allocator<some_struct*>; std::set<_Key, _Compare, _Alloc>::allocator_type = std::allocator<some_struct*>]
       set(const allocator_type& __a)
       ^~~
/usr/include/c++/6/bits/stl_set.h:232:7: note:   no known conversion for argument 1 from ‘main()::<lambda(some_struct*, some_struct*)>’ to ‘const allocator_type& {aka const std::allocator<some_struct*>&}’
/usr/include/c++/6/bits/stl_set.h:224:7: note: candidate: std::set<_Key, _Compare, _Alloc>::set(std::initializer_list<_Tp>, const _Compare&, const allocator_type&) [with _Key = some_struct*; _Compare = bool (*)(some_struct*, some_struct*); _Alloc = std::allocator<some_struct*>; std::set<_Key, _Compare, _Alloc>::allocator_type = std::allocator<some_struct*>]
       set(initializer_list<value_type> __l,
       ^~~
/usr/include/c++/6/bits/stl_set.h:224:7: note:   no known conversion for argument 1 from ‘main()::<lambda(some_struct*, some_struct*)>’ to ‘std::initializer_list<some_struct*>’
/usr/include/c++/6/bits/stl_set.h:210:7: note: candidate: std::set<_Key, _Compare, _Alloc>::set(std::set<_Key, _Compare, _Alloc>&&) [with _Key = some_struct*; _Compare = bool (*)(some_struct*, some_struct*); _Alloc = std::allocator<some_struct*>]
       set(set&& __x)
       ^~~
/usr/include/c++/6/bits/stl_set.h:210:7: note:   no known conversion for argument 1 from ‘main()::<lambda(some_struct*, some_struct*)>’ to ‘std::set<some_struct*, bool (*)(some_struct*, some_struct*)>&&’
/usr/include/c++/6/bits/stl_set.h:199:7: note: candidate: std::set<_Key, _Compare, _Alloc>::set(const std::set<_Key, _Compare, _Alloc>&) [with _Key = some_struct*; _Compare = bool (*)(some_struct*, some_struct*); _Alloc = std::allocator<some_struct*>]
       set(const set& __x)
       ^~~
/usr/include/c++/6/bits/stl_set.h:199:7: note:   no known conversion for argument 1 from ‘main()::<lambda(some_struct*, some_struct*)>’ to ‘const std::set<some_struct*, bool (*)(some_struct*, some_struct*)>&’
/usr/include/c++/6/bits/stl_set.h:186:2: note: candidate: template<class _InputIterator> std::set<_Key, _Compare, _Alloc>::set(_InputIterator, _InputIterator, const _Compare&, const allocator_type&)
  set(_InputIterator __first, _InputIterator __last,
  ^~~
/usr/include/c++/6/bits/stl_set.h:186:2: note:   template argument deduction/substitution failed:
prog.cpp:14:2: note:   candidate expects 4 arguments, 1 provided
  );
  ^
In file included from /usr/include/c++/6/set:61:0,
                 from prog.cpp:1:
/usr/include/c++/6/bits/stl_set.h:169:2: note: candidate: template<class _InputIterator> std::set<_Key, _Compare, _Alloc>::set(_InputIterator, _InputIterator)
  set(_InputIterator __first, _InputIterator __last)
  ^~~
/usr/include/c++/6/bits/stl_set.h:169:2: note:   template argument deduction/substitution failed:
prog.cpp:14:2: note:   candidate expects 2 arguments, 1 provided
  );
  ^
In file included from /usr/include/c++/6/set:61:0,
                 from prog.cpp:1:
/usr/include/c++/6/bits/stl_set.h:154:7: note: candidate: std::set<_Key, _Compare, _Alloc>::set(const _Compare&, const allocator_type&) [with _Key = some_struct*; _Compare = bool (*)(some_struct*, some_struct*); _Alloc = std::allocator<some_struct*>; std::set<_Key, _Compare, _Alloc>::allocator_type = std::allocator<some_struct*>]
       set(const _Compare& __comp,
       ^~~
/usr/include/c++/6/bits/stl_set.h:154:7: note:   no known conversion for argument 1 from ‘main()::<lambda(some_struct*, some_struct*)>’ to ‘bool (* const&)(some_struct*, some_struct*)’
/usr/include/c++/6/bits/stl_set.h:142:7: note: candidate: std::set<_Key, _Compare, _Alloc>::set() [with _Key = some_struct*; _Compare = bool (*)(some_struct*, some_struct*); _Alloc = std::allocator<some_struct*>]
       set()
       ^~~
/usr/include/c++/6/bits/stl_set.h:142:7: note:   candidate expects 0 arguments, 1 provided

Is it possible to make this working and how?

PS. If anyone wishes to know why do I want to do this: The struct contains a std::vector of ints, all vectors of the same size that is not known compile time, and I need to put these structs in many sets, each sorting them by another index of this vector.

  • I'm reopening this question because `std::set` doesn't require the lambda to be passed as a function pointer and the dupe talks about passing lambdas as function pointers. – chris Nov 26 '17 at 20:07
  • 1
    Only lambdas without a capture are convertible to a plain function pointer. Make it `set> s_s`, then you can use an arbitrary lambda or other function object as its comparator (provided it satisfies the requirements, of course). – Igor Tandetnik Nov 26 '17 at 20:36
  • You might also be interested in [`Boost.MultiIndex` library](http://www.boost.org/doc/libs/1_65_1/libs/multi_index/doc/index.html). – Igor Tandetnik Nov 26 '17 at 20:40
  • @IgorTandetnik Many thanks. I'm using `std::function` for the first time, I learned something new! Unfortunately, I can't use Boost, this is an algorithmic task, I can only use stdlib. If you posted this as an answer I'd mark it accepted. –  Nov 26 '17 at 20:52

0 Answers0