I am trying to clear a std::queue using the example in https://stackoverflow.com/a/709161/837451 via a swap. However, it doesn't seem to work with a lambda comparator due to the "deleted function" error.
Minimal working failing example:
#include <queue>
#include <vector>
using namespace std;
int main(){
typedef pair<int,float> ifpair;
auto comp = []( ifpair a, ifpair b ) { return a.second > b.second; };
typedef priority_queue< ifpair , vector<ifpair>, decltype( comp ) > t_npq;
t_npq npq( comp );
//do something with npq. finish using it (without emptying it) and clear for next round
t_npq empty( comp );
swap(npq , empty);
}
Compile with
g++ -std=c++11 /tmp/test.cpp -o /tmp/o
And I get the following error:
/usr/include/c++/4.8/bits/move.h:176:11: error: use of deleted function ‘main()::__lambda0& main()::__lambda0::operator=(const main()::__lambda0&)’
__a = _GLIBCXX_MOVE(__b);
^
/tmp/test.cpp:6:18: note: a lambda closure type has a deleted copy assignment operator
g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.8.1-10ubuntu9' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.1 (Ubuntu/Linaro 4.8.1-10ubuntu9)
I'm kind of curious what exactly is going on here but more importantly I would really like to know how to make this work.
While the result of a lambda expression is move constructible it isn't necessarily move assignable and certainly not copyable. I would just bypass the problem by using a
std::reference_wrapper<decltype(comp)>
for the comparator object:Since the full type information of the lambda expression is retained by the reference wrapper, this should work even if the closure isn't empty and, where viable, it should be possible to inline the function.