I have a bit of code which fails under VS2015, but works under GCC. I'm pretty sure the bug is with Visual Studio but want to be sure that my understanding of decltype(auto) is correct.
#include <iostream>
using namespace std;
string zero_params()
{
return "zero_params called.";
}
template< typename F >
auto test1( F f ) -> decltype(auto)
{
return f();
}
int main() {
cout << std::is_rvalue_reference< decltype(test1(zero_params)) >::value << endl;
cout << test1(zero_params) << endl;
cout << "Done!" << endl;
return 0;
}
Under Visual Studio the string returned by zero_params is deduced to be an rvalue reference. Furthermore the destructor of that object is called inside test1() where the return from the call to f happens (which seems a reasonable place to destruct a && object).
Under GCC the string returned is not deduced to be an rvalue reference. The destructor is called after use in the cout statement as I'd expect.
Specifying the return type to be 'string' instead of decltype(auto) under Visual Studio fixes it, as does using remove_reference_t on the return of f() inside test1.
My expectation would be that GCC is correct as the function signature for zero_params() is string, not string&& so I would expect the non-reference to 'bubble up' to the return type of test1 if it uses decltype(auto).
Is this a correct assessment?
LATE EDIT:
Another way I've found to get around this with VS2015 is to wrap the function given to test1 in a lambda:
cout << test1(zero_params) << endl;
to:
cout << test1( [](auto&&... ps) { return zero_params(std::forward<decltype(ps)>(ps)...); } ) << endl;
So based on the comments we can conclude:
This is a bug in VS2015 preview
There are workarounds
The bug has been reported
The bug is that:
The compiler should have deduced the return type to be string
It actually deduced it to be string &&
Thus it destroyed the value prematurely
The workarounds are:
Don't use decltype(auto) for the function's return type
Wrap the function in a lambda expression before passing it in
Related
What is the difference between std::invocable and std::regular_invocable? Based on the description from
https://en.cppreference.com/w/cpp/concepts/invocable I would expect that the std::regular_invocable concept doesn't allow to change the state of of the function object when it is called (or at least the result of the calling should always return the same result).
Why the code below compiles?
Compiled with a command: g++-10 -std=c++2a ./main.cc.
#include <iostream>
#include <concepts>
using namespace std;
template<std::regular_invocable F>
auto call_with_regular_invocable_constraint(F& f){
return f();
}
template<std::invocable F>
auto call_with_invocable_constraint(F& f){
return f();
}
class adds_one {
int state{0};
public:
int operator()() {
state++;
return state;
}
};
int main()
{
auto immutable_function_object([]() { return 1; });
adds_one mutable_function_object;
// I would expect only first three will be compiled and the last one will fail to compile because the procedure is
// not regular (that is does not result in equal outputs given equal inputs).
cout << call_with_invocable_constraint(immutable_function_object) << endl;
cout << call_with_invocable_constraint(mutable_function_object) << endl;
cout << call_with_regular_invocable_constraint(immutable_function_object) << endl;
cout << call_with_regular_invocable_constraint(mutable_function_object) << endl; // Compiles!
}
Output of the program:
1
1
1
2
From the reference:
Notes
The distinction between invocable and regular_invocable is purely semantic.
This means that there is no way for the compiler to enforce the distinction through the concepts system, since that can only check syntactic properties.
From the introduction to the concepts library:
In general, only the syntactic requirements can be checked by the compiler. If the validity or meaning of a program depends whether a sequenced of template arguments models a concept, and the concept is satisfied but not modeled, or if a semantic requirement is not met at the point of use, the program is ill-formed, no diagnostic required.
Hypothetically, we could write:
template< class F, class... Args >
concept regular_invocable = invocable<F, Args...> &&
requires(F&& f, Args&&... args) {
auto prev = f;
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
assert(f == prev);
// TODO assert that `args` are unchanged
// TODO assert that invoking `f` a second time gives the same result
};
However, this would not actually test that the assertion holds, since a requires clause is not invoked at run time but only checked at compile time.
regular_invocable tells the user of the function that it will assume, that the result calling that regular_invocable function with the same value of the arguments will result in the same return value, and might cache that result due to that.
Caching the result could either be done by the function that expects regular_invocable or the compiler could use that information to optimize away multiple function calls to the regular_invocable function when the value of the arguments stay the same. So right now it can be seen as documentation and compiler hint.
Similar to const_cast it might not always be possible for the compiler to check if it is valid. Due to that and because there is currently not attribute/keyword in the standard to mark a function to always return the same value, there is right now no way to enforce at compile time that the function passed regular_invocable really matches that requirement.
I want use .net's System.Threading.Tasks.Task.ContinueWith in C++, so I write the following function..
#include <iostream>
#include <functional>
#include <future>
template <typename Func, typename Ret>
auto continue_with(std::future<Ret> &&fu, Func func)
-> std::future<decltype(func(fu.get()))>
{
return std::async(
[fu = std::move(fu), func]() mutable { return func(fu.get()); }
);
}
template <typename Func>
auto continue_with(std::future<void> &&fu, Func func)
-> std::future<decltype(func())>
{
return std::async(
[fu = std::move(fu), func]() mutable { fu.get(); return func(); }
);
}
int main()
{
std::future<void> fu = std::async([]{ std::cout << "fu" << std::endl; });
std::future<void> fu2 = continue_with(
std::move(fu),
[]{ std::cout << "fu2" << std::endl; }
);
fu2.get();
std::cout << "fu continue complete" << std::endl;
std::future<int> retfu = std::async([]{ std::cout << "retfu" << std::endl; return 3; });
std::future<int> retfu2 = continue_with(
std::move(retfu),
[](int result){ std::cout << "retfu2 " << result << std::endl; return result + 1; }
);
int ret = retfu2.get();
std::cout << "retfu continue complete : " << ret << std::endl;
std::cin.get();
}
This code works on gcc 4.8.2 with -std=c++1y. (I don't know why, but it works with -std=c++11, too)
But it doesn't work on VC++ 2013. I guess it's because init-capture, a C++14 feature. How can I run this code with VC++ 2013?
(I want to use lambda, so please don't tell me "use just function-object struct!")
(I tried Move capture in lambda, but it doesn't work..)
(I'll appreciate if you not only answer my question but also imporve my code)
Unfortunately, this feature was not present yet in Visual Studio 2013. It was released in June 2014 with the Visual Studio "14" CTP (community tech preview, which is alpha-quality and not ready for production code). To quote:
Here are the improvements for Visual C++:
Generalized lambda capture: You can assign the result of evaluating an
expression to a variable in the capture clause of a lambda. This
allows an instance of a move-only type to be captured by value.
As was pointed out in the comments: as a work-around for Visual Studio 2013, you can make your own function object with local variables initialized through the constructor. Yes, this sucks, but it has been the standard trick before lambdas were invented. It was also the case with polymorphic lambdas until they were supported (workaround: function object with templated operator()) and currently with the currently disallowed constexpr lambdas (workaround: constexpr function object of literal type).
2 other options exist, using std::bind and writing a move on copy wrapper.
so you could do
return std::async(std::bind(
[func](std::future<void> & fu) mutable { fu.get(); return func(); },
std::move(fu)
);
The move on copy wrapper I can just point you to How to capture std::unique_ptr "by move" for a lambda in std::for_each
Given the following test code
#include <iostream>
#include <tr1/functional>
using namespace std;
struct cl {
cl(){ cout << " cl()\n"; }
cl(const cl& from){ cout << " cl()[copy]\n"; }
~cl(){ cout << " ~cl()\n";}
};
void f1(const cl& data){}
void f2(const cl* pData){}
int main(int c, char** a)
{
cout << "enter:\n";
cl data;
cout << "ref:\n";
tr1::bind(&f1, data);
cout << "ptr:\n";
tr1::bind(&f2, &data);
cout << "exit:\n";
return 0;
}
I get the following output:
$ g++ tr1BindDtorTest.cpp && ./a.out
enter:
cl()
ref:
cl()[copy]
cl()[copy]
cl()[copy]
~cl()
~cl()
~cl()
ptr:
exit:
~cl()
When I create a binding involving references to my class/struct objects are created and destroyed multiple times.
Same exact test but with pointers there are no such objects
I can't see why the behaviour will be different between pass by value & reference, I always thought of reference as syntactic sugar for pointer, and so reasoned that the behaviours should be identical.
Anyone care to explain?
[g++ 4.4.6 linux & 4.2.1 on macos]
Instead of this:
tr1::bind(&f1, data);
You need this:
tr1::bind(&f1, tr1::ref(data));
Boost has the same thing: boost::ref() must be used inside boost::bind() if you want the bound function object to store a reference to the data. Otherwise, the data will always be copied into the bound function object produced by bind().
See cppreference documentation:
The arguments to bind are copied or moved, and are never passed by
reference unless wrapped in std::ref or std::cref.
this piece of code is not something unknown to JS developers
function get_counter()
{
return (
function() {
var c = 0;
return function() { return ++c; };
})();
}
it basically creates a which creates different enumerators. So I was wondering if same thing can be done in C++11 with new lambda semantics? I ended up writing this piece of C++ which unfortunately does not compile!
int main()
{
int c;
auto a = [](){
int c = 0;
return [&](){
cout << c++;
};
};
return 0;
}
so I was wondering if there is a workaround to get it compiled and if there is how can compiler make this code run correctly? I mean it has to create separate enumerators but it should also collect garbage (unused c variables).
by the way I'm using VS2012 compiler and it generates this error:
Error 2 error C2440: 'return' : cannot convert from 'main::<lambda_10d109c73135f5c106ecbfa8ff6f4b6b>::()::<lambda_019decbc8d6cd29488ffec96883efe2a>' to 'void (__cdecl *)(void)' c:\users\ali\documents\visual studio 2012\projects\test\test\main.cpp 25 1 Test
Your code has a bug in that it contains a dangling reference; the c reference will refer to the local variable in the outer lambda, which will be destroyed when the outer lambda returns.
You should write it using a mutable by-value lambda capture:
auto a = []() {
int c = 0;
return [=]() mutable {
cout << c++;
};
};
This relies on a post-standard extension to allow multiple statements in a return-type-deducing lambda; Is there a reason on not allowing lambdas to deduce the return type if it contains more than one statement? The easiest way to fix it is to supply a parameter so that the lambda contains only a single statement:
auto a = [](int c) {
return [=]() mutable {
cout << c++;
};
};
Unfortunately default parameters aren't allowed in lambdas, so you'd have to call this as a(0). Alternatively at the cost of readability you could use a nested lambda call:
auto a = []() {
return ([](int c) {
return [=]() mutable {
cout << c++;
};
})(0);
};
The way this works is that when a executes the inner lambda copies all the referenced variables into an instance of its closure type, which here would be something like:
struct inner_lambda {
int c;
void operator()() { cout << c++; }
};
The instance of the closure type is then returned by the outer lambda, and can be invoked and will modify its copy of c when called.
Overall, your (fixed) code is translated to:
struct outer_lambda {
// no closure
struct inner_lambda {
int c; // by-value capture
// non-const because "mutable"
void operator()() { cout << c++; }
}
// const because non-"mutable"
inner_lambda operator()(int c) const {
return inner_lambda{c};
}
};
If you left c as a by-reference capture, this would be:
struct outer_lambda {
// no closure
struct inner_lambda {
int &c; // by-reference capture
void operator()() const { cout << c++; } // const, but can modify c
}
inner_lambda operator()(int c) const {
return inner_lambda{c};
}
};
Here inner_lambda::c is a dangling reference to the local parameter variable c.
It's a natural limitation of C++ that a lambda which captures by reference can't use the captured variable any more, once the variable no longer exists. So even if you get it to compile, you can't return this lambda from the function in which it appears (that also happens to be a lambda, but that's irrelevant), because the automatic variable c is destroyed on return.
I think the code you need is:
return [=]() mutable {
cout << c++;
};
I haven't tested it and I don't know what compiler versions support it, but that's a capture-by-value, with mutable to say that the captured value can be modified by the lambda.
So each time you call a you get a different counter with its own count starting from 0. Each time you call that counter, it increments its own copy of c. As far as I understand Javascript (not far), that's what you want.
I think the problem is that the compiler cannot deduce the return type of the outer lambda (that assigned to a) because it consists of more than a simple one line return. But unfortunately there is also no way to explicitly state the type of the inner lambda. So you will have to return a std::function, which comes with some additional overhead:
int main()
{
int c;
auto a = []() -> std::function<void()> {
int c = 0;
return [=]() mutable {
std::cout << c++;
};
};
return 0;
}
And of course you have to capture by-value, like Steve already explained in his answer.
EDIT: As to why the exact error is that it cannot convert the returned inner lambda to void(*)() (pointer to void() function), I only have some guesses because I don't have much insight into their lambda implementation, which I'm not sure is that stable or standard-conformant at all.
But I think VC at least tries to deduce the return type of the inner lambda and realizes that it returns a callable. But then it somehow incorrectly assumes this inner lambda to not capture (or they are not able to determine the inner lambda's type), so they just make the outer lambda return a simple function pointer, which would indeed work if the inner lambda wouldn't capture anything.
EDIT: And like ecatmur states in his comment, returning a std::function is even neccessary when making an actual get_counter function (instead of a lambda), since normal functions don't have any automatic return type deduction.
The first thing you should know is that even if you get the syntax to compile, the semantics are different. In C++ lambdas that capture by reference capture just a plain reference, that will not extend the lifetime of the object bound by that reference. That is, the lifetime of c is bound to the lifetime of the enclosing lambda:
int main()
{
int c;
auto a = [](){
int c = 0;
return [&](){
return ++c;
};
}(); // Note: added () as in the JS case
std::cout << a() << a();
return 0;
}
After adding the missing () so that the external lambda is evaluated, your problem is that the c that is held by reference in the returned lambda is no longer valid after the evaluation of the full expression.
That being said, it is not too complex to make that work at the cost of an extra dynamic allocation (which would be the equivalent of the JS case):
int main()
{
int c;
auto a = [](){
std::shared_ptr<int> c = std::make_shared<int>(0);
return [=](){
return ++(*c);
};
}(); // Note: added () as in the JS case
std::cout << a() << a();
return 0;
}
That should compile and work as expected. Whenever the internal lambda is released (a goes out of scope) the counter will be freed from memory.
This works on g++ 4.7
#include <iostream>
#include <functional>
std::function<int()> make_counter() {
return []()->std::function<int()> {
int c=0;
return [=]() mutable ->int {
return c++ ;
};
}();
}
int main(int argc, char * argv[]) {
int i = 1;
auto count1= make_counter();
auto count2= make_counter();
std::cout << "count1=" << count1() << std::endl;
std::cout << "count1=" << count1() << std::endl;
std::cout << "count2=" << count2() << std::endl;
std::cout << "count1=" << count1() << std::endl;
std::cout << "count2=" << count2() << std::endl;
return 0;
}
Valgrind doesn't complain about this at all. Every time I call make_counter, valgrind reports an additional allocation and free, so I assume the lambda meta programming code is inserting the allocation code for the memory for variable c (I guess I can check the debugger). I wonder if this is Cxx11 compliant or just g++ specific. Clang 3.0 will not compile this because it doesn't have std::function (maybe I can try using boost function).
I know this is late, but in C++14 and later you can now initiliaze a lambda capture, leading to more simple code:
auto a = []() {
return [c=0]() mutable {
cout << c++;
};
};
How can I bind to a function that takes default arguments, without specifying the default arguments and then call it without any arguments?
void foo(int a, int b = 23) {
std::cout << a << " " << b << std::endl;
}
int main() {
auto f = std::bind(foo, 23, 34); // works
f();
auto g = std::bind(foo, 23); // doesn't work
g();
using std::placeholders::_1;
auto h = std::bind(foo, 23, _1); // doesn't work either
h();
}
Basically, any time you write foo(x) the compiler translates it to foo(x, 23);. It only works if you actually have a directly call with the function name. You can' t, for example, assign &foo to a void(*)(int), because the function's signature is void(int, int). Default parameters play no part in the signature. And if you assign it to a void(*)(int, int) variable, the information about the default parameter is lost: you can't take advantage of the default parameter through that variable. std::bind stores a void(*)(int, int) somewhere in its bowels, and thus loses the default parameter information.
There is no way in C++ to get the default value of a parameter from outside the function, so you're stuck with manually providing the default value when you bind.
I think you could simulate the behaviour you want using a lambda.
Something along the lines of this:
auto g = [] (){ foo( 23 ); };
EDIT: Just checked, and seems to work fine: http://ideone.com/SPSvi
I have two solutions:
1 - You can overload foo() and have it call the original with defaults:
void foo(int a, int b)
{
std::cout << a << " " << b << std::endl;
}
inline void foo(int a)
{
foo(a, 23);
}
2 - You can use a static variable as default and then use it in the binding process:
static int foo_default_b = 23;
void foo(int a, int b = foo_default_b)
{
std::cout << a << " " << b << std::endl;
}
auto g = std::bind(foo, 23, foo_default_b);
g();
This answer disagrees with R. Martinho Fernandes' answer. You can indeed use boost::bind to bind to the default parameters, you just need to put placeholders in, as so:
boost::bind<void (int, int)>(foo, _1, _2)(12);
This will call foo(12, 23), as expected. Although I didn't test this specific code, I've done something similar in my code based on the answer linked above, and it works in gcc 4.8.5.
Hmm, I just noticed that this is asking about std::bind, not boost::bind. I don't know what differences there are, if any.