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.)