Why this code snippet compiles with GCC 4.9.3,
#include<memory> #include<string> #include<cstdio> int ExecCmd(const std::string& cmd, std::string& output) { int ret = 0; const auto deleter= [&ret](FILE* file){ if(NULL==file) { ret = -1; } else { ret = pclose(file); } }; { std::unique_ptr<FILE, decltype(deleter) > pipe{popen(cmd.c_str(), "r"), deleter}; } return ret; } int main() { } whereas this code snippet does not compile with GCC 4.9.3:
#include <memory> #include <iostream> #include <string> #include <cstdio> #include<cstdio> int ExecCmd(const std::string& cmd, std::string& ) { int ret = 0; auto deleter{[&ret](FILE* file){ if(NULL==file) { ret = -1; } else { ret = pclose(file); } } }; { std::unique_ptr<FILE, decltype(deleter)> pipe(popen(cmd.c_str(), "r"), deleter); } return ret; } int main() { } Here is what the compiler complains:
In file included from /opt/compiler-explorer/gcc-4.9.3/include/c++/4.9.3/memory:81:0, from <source>:1: /opt/compiler-explorer/gcc-4.9.3/include/c++/4.9.3/bits/unique_ptr.h: In instantiation of 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = _IO_FILE; _Dp = std::initializer_list<ExecCmd(const string&, std::string&)::<lambda(FILE*)> >]': <source>:24:87: required from here /opt/compiler-explorer/gcc-4.9.3/include/c++/4.9.3/bits/unique_ptr.h:236:16: error: no match for call to '(std::unique_ptr<_IO_FILE, std::initializer_list<ExecCmd(const string&, std::string&)::<lambda(FILE*)> > >::deleter_type {aka std::initializer_list<ExecCmd(const string&, std::string&)::<lambda(FILE*)> >}) (_IO_FILE*&)' get_deleter()(__ptr); ^ Note:
- I only have to use
GCC 4.9.3. - I always use
auto lambda{[](...){...}}to construct lambdas. This is the first time that I encounter such problem. And It makes dazed that should I never construct lambdas in this way in the future withGCC4.9.3? Or under what conditions, I should pay attention to such a problem?
Thanks to @J6t, @JeJo. I found how to make the code snippet complies.
I thought and thought, but I still can't find the answer.
Could anybody shed some light on this matter?
auto deleter = [&..]....work, butauto deleter {[&...]....not? Theconstin the first version does not change anything.auto x{1}; int y = x;-xis aninitializer_list, not anint. This seems to be a bug in 4.9.3. The solution is to not combineautowith a braced initializer. (It's not clear why you would desire to do this with the lambda but not withret.)