Empty lambda capture still shadows outer scope? - c++11

An empty lambda capture list [] creates a plain function without a closure object. Why, then, given this example:
int main(int argc, const char *argv[]) {
auto _foo = [] (int argc) {
return argc - 1;
};
return _foo(argc);
}
does gcc (4.8.5 and 5.4.0) warn that the argc of the lambda shadows the argc variable of the outer scope?
In lambda function:
warning: declaration of ‘int argc’ shadows a parameter [-Wshadow]
auto _foo = [] (int argc) {
^
note: shadowed declaration is here
int main(int argc, const char *argv[]) {
^
After all, there is no outer/surrounding closure state that could be shadowed.

It is a warning. The code within the lambda could confuse readers about which variable is being used.
The warning is not about bad behavior, just unreadable code, and the fact it is a non-capturing lambda doesn't really make the code more readable.
The rules for shadowing variables in an inner scope are just as clear for the rules for a non-capturing lambda and a parameter with the same name, and the warning exists for the same reason.

Related

std::shared_ptr<double[2]> constructor problems

The current C++ compilers fail to find a suitable overload for std::shared_ptr when using a C-array as a type.
I can make it a real std::array object and that works, but the library I'm linking against (fftw3) has already created the typedef and uses it in all of it's C-API calls.
#include <memory>
typedef double fftw_complex[2];
int main(int argc, char* argv[])
{
fftw_complex bob; //works fine
bob[0]=2; bob[1]=-1; //works fine
std::shared_ptr<fftw_complex> handle; //works fine
std::shared_ptr<double> other(new double[35]); //works fine
handle = std::shared_ptr<fftw_complex>(new fftw_complex[35]);//can't find constructor
return 0;
}
Up until a few months ago this worked fine with all compilers. With the update to gcc to version 7.3, 8.2, and 9 I now get an error when trying to compile the non-void constructor. I suspect it is because of the "improvements" to std::shared_ptr to automatically handle when T is an array type.
I get the error
complex_shared.cpp:12:61: error: no matching function for call to 'std::shared_ptr<double [2]>::shared_ptr(double (*)[2])'
12 | handle = std::shared_ptr<fftw_complex>(new fftw_complex[35]);
and the somewhat difficult to parse error message
note: candidate: 'template<class _Yp, class> std::shared_ptr<_Tp>::shared_ptr(_Yp*)'
139 | shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
| ^~~~~~~~~~
/usr/local/Cellar/gcc/9.2.0/include/c++/9.2.0/bits/shared_ptr.h:139:2: note: template argument deduction/substitution failed:
/usr/local/Cellar/gcc/9.2.0/include/c++/9.2.0/bits/shared_ptr.h: In substitution of 'template<class _Tp> template<class ... _Args> using _Constructible = typename std::enable_if<std::is_constructible<std::__shared_ptr<_Tp>, _Args ...>::value>::type [with _Args = {double (*)[2]}; _Tp = double [2]]':
/usr/local/Cellar/gcc/9.2.0/include/c++/9.2.0/bits/shared_ptr.h:137:30: required from here
/usr/local/Cellar/gcc/9.2.0/include/c++/9.2.0/bits/shared_ptr.h:106:8: error: no type named 'type' in 'struct std::enable_if<false, void>'
106 | using _Constructible = typename enable_if<
it seems you have to let std::shared_ptr know that this is not a normal pointer but is indeed a pointer to an array
#include <memory>
typedef double fftw_complex[2];
int main(int argc, char* argv[])
{
fftw_complex bob;
bob[0]=2; bob[1]=-1;
std::shared_ptr<fftw_complex[]> handle;
std::shared_ptr<double> other(new double[35],[](double* p){ delete[] p;});
std::shared_ptr<double[]> nother(new double[35]); //std::shared_ptr will call delete[]
handle = std::shared_ptr<fftw_complex[]>(new fftw_complex[35], [](fftw_complex* p){ /* special delete logic*/;});
return 0;
}
to be clear, I have to use the fftw_malloc and fftw_free functions for this memory, so I will be providing my own deleter for the fftw_complex type. delete[] is incorrect for these library-provided data elements.

issue with <libgen.h> and using basename

Unable to get basename to work in C++, I am trying to just get the code to compile.
This is for a school assignment and I have tried to see if it is my stdlib having issues -- however, it seems that the problem is that
'''c++
#include<iostream>
#include<cstring>
#include<libgen.h>
int main(){
const char *ch = "asdfasdf/asdf.cpp";
std::cout<<basename(ch) << std::endl;
std::cout<<dirname(strdup(ch)) << std::endl;
return 0;
}
I was supposed to print out the output of ch, however, instead I get the error message:
test.cpp:8:14: error: no matching function for call to 'basename'
std::cout<enter code here
/usr/include/libgen.h:40:7: note: candidate function not viable: 1st argument ('const char *') would lose const qualifier
char *basename(char *);
^
1 error generated.
basename's argument is char*, so this function may modify passed data. You cannot pass const char* - pointer to only-read data into basename because it would let basename modify const data - not allowed.
Create your input as modifiable array:
char ch[] = "asdfasdf/asdf.cpp";

How can I return char array with boost::optional

I try to return simple array with boost::optional
boost::optional<const char *> foo () {
char ar[100] = {};
return boost::make_optional(true, ar);
}
and I got the following error:
could not convert ‘boost::make_optional(bool, const T&) [with T = char [100]](ar)’ from ‘boost::optional<char [100]>’ to ‘boost::optional<const char*>’ return boost::make_optional(true, ar);
How can I handle such confusion?
Closest you can do is by using a wrapper with value semantics.
That wrapper is std::array:
boost::optional<std::array<char, 100> > foo () {
std::array<char, 100> ar {};
return boost::make_optional(true, ar);
}
About arrays vs. pointers:
How do I use arrays in C++?
boost::make_optional deduced ar as char [100] type, but it expected const char *. By default implicit casting is not happened in template parameter deduction.
If you want to use raw pointer, it is possible to use the following solution:
boost::optional<const char *> foo () {
char ar[100] = {};
return boost::make_optional(true, static_cast<const char *>(ar));
}
But in this case you lose information how many elements located in this array and maybe better to use in foo() function std::vector or std::array as in example of sehe
Good luck !!

C++11 - lambda function pass vector in capture and modify it

I have this code:
#include <iostream>
#include <functional>
#include <vector>
int main () {
std::vector<int> kk;
kk.push_back(2);
std::function<int(int)> foo = std::function<int(int)>([kk](int x)
{
kk.push_back(1);
return kk[0]+1;
});
std::cout << "foo: " << foo(100) << '\n';
return 0;
}
Why I cannot modify vector kk, passed via capture, inside lambda function?
I got this error:
11:21: error: passing 'const std::vector' as 'this' argument of
'void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp,
_Alloc>::value_type&&) [with _Tp = int; _Alloc = std::allocator; std::vector<_Tp, _Alloc>::value_type = int]' discards qualifiers
[-fpermissive]
I can pass it by reference, but problem is, that it will go out of scope if my lambda is called from thread and vector will no longer be available.
By default, a closure type declares its operator() as const-qualified member function. Which means objects captured by copy cannot be modified inside the lambda. To make the operator() a non-const member function, you have to mark the lambda mutable:
std::function<int(int)> foo{[kk](int x) mutable
{
kk.push_back(1);
return kk[0]+1;
}};
[Live example]
(I also took the liberty of removing the double type specification in the declaration).
Of course, bear in mind that the copy of kk made in the capture is local to the lambda object. The local variable kk in main will not be modified by calling foo.

How to decorate a function in C++

I would like to achieve the following
#include <iostream>
unsigned foo(int i) {return i;};
unsigned bar(unsigned(*p)()) {/*Do important work*/return p();};
int main(void){
int integer = 42;
auto lambda = [integer] () -> unsigned {return foo(integer);};
unsigned number = bar(lambda);
std::cout << number << std::endl;
}
That is, bar is expecting a pointer to function with no arguments and returning unsigned. I can easily write a wrapper unsigned baz() {return foo(42);};and pass that one to bar(), but this has two drawbacks
it's a separate function, while I would prefer to construct the wrapper inline
I have to write a new wrapper for each expected value of `integer.
The idea is that bar() is doing some work, in the process invoking the function, that was passed to it. I have a suitable function, but it has an extra argument. That extra argument, however, is known at the point of passing the function to bar().
Is there a way to pull this off, or should I forget this approach and use templates? I have control over changing the interface (e.g. change the function pointer argument to std::function).`

Resources