I am attempting to figure out how to move (or just copy if a move is not available) variadic parameters into a lambda within a templated function.
I am testing this with a move-only class (see below) because this would be the "worst-case" that needs to work with my template.
class MoveOnlyTest {
public:
MoveOnlyTest(int a, int b = 20, int c = 30) : _a(a), _b(b), _c(c) {
std::cout << "MoveOnlyTest: Constructor" << std::endl;
}
~MoveOnlyTest() {
std::cout << "MoveOnlyTest: Destructor" << std::endl;
}
MoveOnlyTest(const MoveOnlyTest& other) = delete;
MoveOnlyTest(MoveOnlyTest&& other) :
_a(std::move(other._a)),
_b(std::move(other._b)),
_c(std::move(other._c))
{
std::cout << "MoveOnlyTest: Move Constructor" << std::endl;
other._a = 0;
other._b = 0;
other._c = 0;
}
MoveOnlyTest& operator=(const MoveOnlyTest& other) = delete;
MoveOnlyTest& operator=(MoveOnlyTest&& other) {
if (this != &other) {
_a = std::move(other._a);
_b = std::move(other._b);
_c = std::move(other._c);
other._a = 0;
other._b = 0;
other._c = 0;
std::cout << "MoveOnlyTest: Move Assignment Operator" << std::endl;
}
return *this;
}
friend std::ostream& operator<<(std::ostream& os, const MoveOnlyTest& v) {
os << "{a=" << v._a << "}";
return os;
}
private:
int _a;
int _b;
int _c;
};
And here is the test code I am attempting to get working:
void test6() {
std::cout << "--------------------" << std::endl;
std::cout << " TEST 6 " << std::endl;
std::cout << "--------------------" << std::endl;
MoveOnlyTest v(1, 2, 3);
test6_A(std::move(v));
}
void test6_A(MoveOnlyTest v) {
std::cout << "test6_A()" << std::endl;
test6_B(test6_C, v);
}
template <typename ... ARGSF, typename ... ARGS>
void test6_B(void(*fn)(ARGSF...), ARGS&&... args) {
std::cout << "test6_B()" << std::endl;
//What do I need to get args to be moved/copied into the lambda
auto lambda = [fn, args = ???]() mutable {
(*fn)( std::forward<ARGS>(args)... );
};
lambda();
}
void test6_C(MoveOnlyTest v) {
std::cout << "test6_C()" << std::endl;
std::cout << "v = " << v << std::endl;
}
I am trying to have the exact same behavior as below, only using a generic template so that I can create a lambda which captures and arguments, and calls any function with those arguments.
void test5() {
std::cout << "--------------------" << std::endl;
std::cout << " TEST 5 " << std::endl;
std::cout << "--------------------" << std::endl;
MoveOnlyTest v(1, 2, 3);
test5_A(std::move(v));
}
void test5_A(MoveOnlyTest v) {
std::cout << "test5_A()" << std::endl;
auto lambda = [v = std::move(v)]() mutable {
test5_B(std::move(v));
};
lambda();
}
void test5_B(MoveOnlyTest v) {
std::cout << "test5_B()" << std::endl;
std::cout << "v = " << v << std::endl;
}
To be clear, I don't want to perfectly capture the arguments as in c++ lambdas how to capture variadic parameter pack from the upper scope I want to move them if possible and, if not, copy them (the reason being is that I plan to store this lambda for later execution thus the variables in the stack will no longer be around if they are just captured by reference).
To be clear, I don't want to perfectly capture the arguments as in c++
lambdas how to capture variadic parameter pack from the upper scope I
want to move them if possible
Just using the same form:
auto lambda = [fn, ...args = std::move(args)]() mutable {
(*fn)(std::move(args)...);
};
In C++17, you could do:
auto lambda = [fn, args = std::tuple(std::move(args)...)]() mutable {
std::apply([fn](auto&&... args) { (*fn)( std::move(args)...); },
std::move(args));
};
Related
I wrote a generic class for handling and executing a function pointer. This is a simplified equivalent of std::function and std::bind. To handle member functions I use cast to internal EventHandler::Class type. Question: is it ok to cast it that way? Will it work in all cases when invoking handled function?
template <typename ReturnType, typename... Arguments>
class EventHandler
{
class Class {};
ReturnType (Class::*memberFunction)(Arguments...) = nullptr;
union {
Class *owner;
ReturnType(*function)(Arguments...) = nullptr;
};
public:
EventHandler() = default;
EventHandler(EventHandler &&) = default;
EventHandler(const EventHandler &) = default;
EventHandler &operator=(EventHandler &&) = default;
EventHandler &operator=(const EventHandler &) = default;
EventHandler(ReturnType (*function)(Arguments...)) :
function(function)
{
}
template <typename Owner>
EventHandler(Owner *owner, ReturnType (Owner::*memberFunction)(Arguments...)) :
memberFunction((ReturnType (Class::*)(Arguments...)) memberFunction),
owner((Class *) owner)
{
}
template <typename Owner>
EventHandler(const Owner *owner, ReturnType (Owner::*memberFunction)(Arguments...) const) :
memberFunction((ReturnType (Class::*)(Arguments...)) memberFunction),
owner((Class *) owner)
{
}
ReturnType operator()(Arguments... arguments)
{
return memberFunction ?
(owner ? (owner->*memberFunction)(arguments...) : ReturnType()) :
(function ? function(arguments...) : ReturnType());
}
};
The implementation provides handle for a global function, a member function and a const member function. Obviously there is volatile and const volatile that is not show here for clarity.
EDIT
All the code below is just a representation of all of kinds of supported functions.
class Object
{
public:
double y = 1000;
Object() = default;
Object(double y) : y(y) {}
static void s1(void) { std::cout << "s1()" << std::endl; }
static void s2(int a) { std::cout << "s2(a:" << 10 + a << ")" << std::endl; }
static void s3(int a, float b) { std::cout << "s3(a:" << 10 + a << ", b:" << 10 + b << ")" << std::endl; }
static int s4(void) { std::cout << "s4(): "; return 10 + 4; }
static Object s5(int a) { std::cout << "s5(a:" << 10 + a << "): "; return Object(10 + 5.1); }
static float s6(int a, Object b) { std::cout << "s6(a:" << 10 + a << ", b:" << 10 + b.y << "); "; return 10 + 6.2f; }
void m1(void) { std::cout << "m1()" << std::endl; }
void m2(int a) { std::cout << "m2(a:" << y + a << ")" << std::endl; }
void m3(int a, float b) { std::cout << "m3(a:" << y + a << ", b:" << y + b << ")" << std::endl; }
int m4(void) { std::cout << "m4(): "; return ((int) y) + 4; }
Object m5(int a) { std::cout << "m5(a:" << y + a << "): "; return Object(y + 5.1); }
float m6(int a, Object b) { std::cout << "m6(a:" << y + a << ", b:" << y + b.y << "); "; return ((int) y) + 6.2f; }
void c1(void) const { std::cout << "c1()" << std::endl; }
void c2(int a) const { std::cout << "c2(a:" << y + a << ")" << std::endl; }
void c3(int a, float b) const { std::cout << "c3(a:" << y + a << ", b:" << y + b << ")" << std::endl; }
int c4(void) const { std::cout << "c4(): "; return ((int) y) + 4; }
Object c5(int a) const { std::cout << "c5(a:" << y + a << "): "; return Object(y + 5.1); }
float c6(int a, Object b) const { std::cout << "c6(a:" << y + a << ", b:" << y + b.y << "); "; return ((int) y) + 6.2f; }
};
void f1(void) { std::cout << "f1()" << std::endl; }
void f2(int a) { std::cout << "f2(a:" << a << ")" << std::endl; }
void f3(int a, float b) { std::cout << "f3(a:" << a << ", b:" << b << ")" << std::endl; }
int f4(void) { std::cout << "f4(): "; return 4; }
Object f5(int a) { std::cout << "f5(a:" << a << "): "; return Object(5.1); }
float f6(int a, Object b) { std::cout << "f6(a:" << a << ", b:" << b.y << "); "; return 6.2f; }
Here is the usage example for all of the above functions
int main()
{
std::cout << "=== Global functions" << std::endl;
EventHandler ef1(f1); ef1();
EventHandler ef2(f2); ef2(2);
EventHandler ef3(f3); ef3(3, 3.1f);
EventHandler ef4(f4); std::cout << ef4() << std::endl;
EventHandler ef5(f5); std::cout << ef5(5).y << std::endl;
EventHandler ef6(f6); std::cout << ef6(6, Object(6.1)) << std::endl;
std::cout << std::endl;
std::cout << "=== Member static functions" << std::endl;
EventHandler es1(Object::s1); es1();
EventHandler es2(Object::s2); es2(2);
EventHandler es3(Object::s3); es3(3, 3.1f);
EventHandler es4(Object::s4); std::cout << es4() << std::endl;
EventHandler es5(Object::s5); std::cout << es5(5).y << std::endl;
EventHandler es6(Object::s6); std::cout << es6(6, Object(6.1)) << std::endl;
std::cout << std::endl;
std::cout << "=== Member functions" << std::endl;
Object object(20);
EventHandler em1(&object, &Object::m1); em1();
EventHandler em2(&object, &Object::m2); em2(2);
EventHandler em3(&object, &Object::m3); em3(3, 3.1f);
EventHandler em4(&object, &Object::m4); std::cout << em4() << std::endl;
EventHandler em5(&object, &Object::m5); std::cout << em5(5).y << std::endl;
EventHandler em6(&object, &Object::m6); std::cout << em6(6, Object(6.1)) << std::endl;
std::cout << std::endl;
std::cout << "=== Member const functions" << std::endl;
const Object constObject(30);
EventHandler ec1(&constObject, &Object::c1); ec1();
EventHandler ec2(&constObject, &Object::c2); ec2(2);
EventHandler ec3(&constObject, &Object::c3); ec3(3, 3.1f);
EventHandler ec4(&constObject, &Object::c4); std::cout << ec4() << std::endl;
EventHandler ec5(&constObject, &Object::c5); std::cout << ec5(5).y << std::endl;
EventHandler ec6(&constObject, &Object::c6); std::cout << ec6(6, Object(6.1)) << std::endl;
system("pause");
return 0;
}
Finally - to the point - here an example that shows how much easier in use is the EventHandler I prepared when compared to std::function interface. And actually the reason of such approach.
EventHandler<float, int, Object> example;
example = f6;
example(7, Object(7.1));
example = EventHandler(&object, &Object::m6);;
example(8, Object(8.1));
It’s undefined behavior to call a function through a function pointer(-to-member) of a different type. (Some practical reasons for this rule are that the object’s address might need to be adjusted to call a member function of a base class or that a vtable might be involved.) You can use type erasure to allow calling member functions on objects of different types (which is what std::bind does), or you can (restrict to member functions and) add the class type as a template parameter.
Of course, the usual answer is to just use std::function with a lambda that captures the object in question and calls whatever member function. You can also take the C approach and define various functions with a void* parameter that cast that parameter to a known class type and call the desired member function.
I've been reading about std::forward and I think I understand it well, but I don't think I understand it well enough to use it proficiently enough.
I have a template class that implements a container and has a method called insert. I wanted this method to accept constant references and rvalue references so that if the inserted element is a rvalue reference, it is moved into the container, not copied. For this, I first overloaded the insert method like this:
template <typename U>
void do_some_work(U&& x) noexcept
{
m_data = std::forward<U>(x);
}
void insert(const T& x)
{
do_some_work(x);
}
void insert(T&& x) {
do_some_work(std::forward<T>(x);
}
The problem is, these two functions now have to call an "inner" function that implements the assertion. If the functions are small, I guess this is not a problem, but if they are large, it is best to use templates, like this
template <typename U>
void insert(U&& x)
{
do_some_work(std::forward<U>(x);
}
QUESTION 1: Is this correct?
Now, I want to do the same but with std::vector.
void insert_vector(const std::vector<T>& v) noexcept {
for (std::size_t i = 0; i < v.size(); ++i) {
do_some_work(v[i]);
}
}
void insert_vector(std::vector<T>&& v) noexcept
{
for (std::size_t i = 0; i < v.size(); ++i)
{
do_some_work(std::forward<T>(v[i]));
}
}
QUESTION 2: How do I collapse the insert_vector functions into a single one so that the call to do_some_work is done with
rvalue references when the vector is a rvalue reference (specified with std::move, for example),
constant reference when the vector is not given as an rvalue reference, like in (4) of the MWE below. The following does not work for me
template <typename U>
void insert_vector(U&& v) noexcept
{
for (std::size_t i = 0; i < v.size(); ++i)
{
do_some_work(std::forward<T>(v[i]));
}
}
Here is a minimum working example:
#include <iostream>
#include <vector>
template <typename T>
class my_class
{
private:
T m_data;
private:
template <typename U>
void do_some_more_work(U&& x) noexcept {
m_data = std::forward<U>(x);
}
template <typename U>
void do_some_work(U&& x) noexcept {
do_some_more_work(std::forward<U>(x));
}
public:
void insert(const T& x) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
do_some_work(x);
}
void insert(T&& x) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
do_some_work(std::forward<T>(x));
}
void insert_vector(const std::vector<T>& v) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
for (std::size_t i = 0; i < v.size(); ++i) {
do_some_work(v[i]);
}
}
void insert_vector(std::vector<T>&& v) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
for (std::size_t i = 0; i < v.size(); ++i) {
do_some_work(std::forward<T>(v[i]));
}
}
};
struct my_struct {
my_struct() noexcept = default;
my_struct(int v) noexcept : m_v(v) { }
my_struct(const my_struct& s) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
m_v = s.m_v;
}
my_struct(my_struct&& s) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
m_v = std::move(s.m_v); // not need, but whatever
s.m_v = -1;
}
my_struct& operator= (const my_struct& s) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
m_v = s.m_v;
return *this;
}
my_struct& operator= (my_struct&& s) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
m_v = std::move(s.m_v); // not need, but whatever
s.m_v = -1;
return *this;
}
int m_v;
};
int main() {
my_class<my_struct> mc;
std::cout << "===========================================\n";
{
std::cout << "-------------------------------------------\n";
std::cout << "(1.1)\n";
my_struct s{3};
std::cout << s.m_v << '\n';
mc.insert(s);
std::cout << s.m_v << '\n';
}
{
std::cout << "-------------------------------------------\n";
std::cout << "(1.2)\n";
const my_struct s{3};
std::cout << s.m_v << '\n';
mc.insert(s);
std::cout << s.m_v << '\n';
}
std::cout << "===========================================\n";
{
std::cout << "-------------------------------------------\n";
std::cout << "(2.1)\n";
mc.insert(my_struct{5});
}
{
std::cout << "-------------------------------------------\n";
std::cout << "(2.2)\n";
my_struct s{5};
std::cout << s.m_v << '\n';
mc.insert(std::move(s));
std::cout << s.m_v << '\n';
}
std::cout << "===========================================\n";
{
std::cout << "-------------------------------------------\n";
std::cout << "(3.1)\n";
std::vector<my_struct> v(5);
for (std::size_t i = 0; i < v.size(); ++i) { v[i] = my_struct(i); }
for (const auto& s : v) { std::cout << s.m_v << ' '; } std::cout << '\n';
mc.insert_vector(v);
for (const auto& s : v) { std::cout << s.m_v << ' '; } std::cout << '\n';
}
{
std::cout << "-------------------------------------------\n";
std::cout << "(3.2)\n";
const std::vector<my_struct> v = []() {
std::vector<my_struct> v(5);
for (std::size_t i = 0; i < v.size(); ++i) { v[i] = my_struct(i); }
return v;
}();
for (const auto& s : v) { std::cout << s.m_v << ' '; } std::cout << '\n';
mc.insert_vector(v);
for (const auto& s : v) { std::cout << s.m_v << ' '; } std::cout << '\n';
}
std::cout << "===========================================\n";
{
std::cout << "-------------------------------------------\n";
std::cout << "(4)\n";
std::vector<my_struct> v(5);
for (std::size_t i = 0; i < v.size(); ++i) { v[i] = my_struct(i); }
for (const auto& s : v) { std::cout << s.m_v << ' '; } std::cout << '\n';
mc.insert_vector(std::move(v));
for (const auto& s : v) { std::cout << s.m_v << ' '; } std::cout << '\n';
}
}
I think I found a way to solve this issue. I used the same "technique" as with the regular insert methods. The full implementation of my_class is this. Unfortunately, I could not make a single insert method.
template <typename T>
class my_class {
private:
T m_data;
private:
template <typename U>
void do_some_more_work(U&& x) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
m_data = std::forward<U>(x);
}
template <typename U>
void do_some_work(U&& x) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
do_some_more_work(std::forward<U>(x));
}
public:
template <typename U>
void insert(U&& x) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
do_some_work(std::forward<U>(x));
}
template <typename U>
void insert_vector(U&& v) noexcept {
using elem_t = typename std::remove_reference_t<U>::value_type;
// this is used here for testing purposes.
static_assert(std::is_same_v<elem_t, my_struct>);
std::cout << __PRETTY_FUNCTION__ << '\n';
for (std::size_t i = 0; i < v.size(); ++i) {
if constexpr (std::is_same_v<std::vector<elem_t>, U>) {
do_some_work(std::forward<T>(v[i]));
}
else {
do_some_work(v[i]);
}
}
}
};
I want to make a function that can wrap any lambda to log start/end calls on it.
The code below works except for:
any lambda that has captures
any lambda that returns void (although this can easily be fixed by writing a second function)
#include <iostream>
#include <functional>
template <class T, class... Inputs>
auto logLambda(T lambda) {
return [&lambda](Inputs...inputs) {
std::cout << "STARTING " << std::endl;
auto result = lambda(inputs...);
std::cout << "END " << std::endl;
return result;
};
}
int main() {
int a = 1;
int b = 2;
// works
auto simple = []() -> int {
std::cout << "Hello" << std::endl; return 1;
};
logLambda(simple)();
// works so long as explicit type is declared
auto with_args = [](int a, int b) -> int {
std::cout << "A: " << a << " B: " << b << std::endl;
return 1;
};
logLambda<int(int, int), int, int>(with_args)(a, b);
// Does not work
// error: no matching function for call to ‘logLambda<int(int), int>(main()::<lambda(int)>&)’
auto with_captures = [&a](int b) -> int {
std::cout << "A: " << a << " B: " << b << std::endl;
return 1;
};
logLambda<int(int), int>(with_captures)(b);
}
Is there any way to do this? Macros are also acceptable
Use Raii to handle both void and non-void return type,
and capture functor by value to avoid dangling reference,
and use generic lambda to avoid to have to specify argument your self
It results something like:
template <class F>
auto logLambda(F f) {
return [f](auto... args) -> decltype(f(args...)) {
struct RAII {
RAII() { std::cout << "STARTING " << std::endl; }
~RAII() { std::cout << "END " << std::endl; }
} raii;
return f(args...);
};
}
Call look like:
const char* hello = "Hello";
logLambda([=](const char* s){ std::cout << hello << " " << s << std::endl; })("world");
Demo
That code has undefined behavior.
auto logLambda(T lambda) {
return [&lambda]
You are capturing local parameter by reference.
I'd like to take out members of a temporary without unnecessary moving or copying.
Suppose I have:
class TP {
T _t1, _t2;
};
I'd like to get _t1, and _t2 from TP(). Is it possible without copying/moving members?
I've tried with tuples and trying to "forward" (I don't think it's possible) the members, but the best I could get was a move, or members dying immediately.
In the following playground using B::as_tuple2 ends up with members dying too soon, unless the result is bound to a non-ref type, then members are moved. B::as_tuple simply moves is safe with auto on client side.
I suppose this should be technically possible, since the temporary dies immediately, and the member do die while they could bound to variables on the calling site (Am I wrong?), and structured binding of a similar struct works as intended.
Is it possible to extend/pass life of the member onto an outside variable, or elide the move/copy? I need it with c++14 version, but I couldn't get it to work on c++17 either, so I am interested in both.
Playground:
#include <tuple>
#include <iostream>
using std::cout;
class Shawty {
/**
* Pronounced shouty.
**/
public:
Shawty() : _id(Shawty::id++) {cout << _id << " ctor\n"; }
Shawty(Shawty && s) : _id(Shawty::id++) { cout << _id << " moved from " << s._id << "\n"; }
Shawty(const Shawty & s) : _id(Shawty::id++) { cout << _id << " copied from " << s._id << "\n"; }
Shawty& operator=(Shawty && s) { cout << _id << " =moved from " << s._id << "\n"; return *this;}
Shawty& operator=(Shawty & s) { cout << _id << " =copied from " << s._id << "\n"; return *this;}
~Shawty() {cout << _id << " dtor\n"; }
int _id;
static int id;
};
int Shawty::id = 0;
class B {
public:
auto as_tuple() && {return std::make_tuple(std::move(_s1), std::move(_s2));}
auto as_tuple2() && {return std::forward_as_tuple(std::move(_s1), std::move(_s2));}
private:
Shawty _s1, _s2;
};
struct S {
Shawty _s1, _s2;
};
int main() {
std::cout << "----------\n";
auto [s1, s2] = B().as_tuple2();
std::cout << "---------\n";
auto tpl1 = B().as_tuple2();
std::cout << "----------\n";
std::tuple<Shawty, Shawty> tpl2 = B().as_tuple2();
std::cout << "----------\n";
std::cout << std::get<0>(tpl1)._id << '\n';
std::cout << std::get<1>(tpl1)._id << '\n';
std::cout << std::get<0>(tpl2)._id << '\n';
std::cout << std::get<1>(tpl2)._id << '\n';
std::cout << s1._id << '\n';
std::cout << s2._id << '\n';
std::cout << "--struct--\n";
auto [s3, s4] = S{};
std::cout << s3._id << '\n';
std::cout << s4._id << '\n';
std::cout << "----------\n";
return 0;
}
No. It is not possible to extend the lifetime of more than one member beyond the lifetime of the super object.
So, the only way to "get" members without copying is to keep the super object alive, and refer to them:
// member function
auto as_tuple3() & {
return std::make_tuple(std::ref(_s1), std::ref(_s2));
}
// usage
B b;
auto [s1, s2] = b.as_tuple3();
An example of extending lifetime of the object by binding a reference to a single member. Note that this requires the member to be accessible from where the reference is bound (not the case in your example, where the member is private):
auto&& s1 = B{}._s1;
Add support for structured binding to your B type.
class B {
public:
template<std::size_t I, class Self,
std::enable_if_t< std::is_same_v<B, std::decay_t<Self>>, bool> = true
>
friend constexpr decltype(auto) get(Self&& self) {
if constexpr(I==0)
{
using R = decltype(std::forward<Self>(self)._s1)&&;
return (R)std::forward<Self>(self)._s1;
}
else if constexpr(I==1)
{
using R = decltype(std::forward<Self>(self)._s2)&&;
return (R)std::forward<Self>(self)._s2;
}
}
private:
Shawty _s1, _s2;
};
namespace std {
template<>
struct tuple_size<::B>:std::integral_constant<std::size_t, 2> {};
template<std::size_t N>
struct tuple_element<N, ::B>{using type=Shawty;};
}
Test code:
int main() {
std::cout << "----------\n";
{
auto&& [s1, s2] = B();
}
}
output:
----------
0 ctor
1 ctor
1 dtor
0 dtor
Live example.
This is the best I can do. Note that s1 and s2 are references into a lifetime-extended version of B.
I am using "emplace" method to avoid memory copy.
But, when I am using the "emplace" inside a Lambda function. It always call implicit move constructor.
How I can avoid memory copy inside a Lambda function?
This sample program should not print “I am being moved.”
#include <vector>
#include <iostream>
struct A
{
int a;
A(int t) : a(t)
{
std::cout << "I am being constructed.\n";
}
A(A&& other) : a(std::move(other.a))
{
std::cout << "I am being moved.\n";
}
};
std::vector<A> g_a;
int main()
{
std::cout << "emplace_back:\n";
g_a.emplace_back(1);
std::cout << "emplace_back in lambda:\n";
auto f1 = [](int x) { g_a.emplace_back(x); };
f1(2);
std::cout << "\nContents: ";
for (A const& t : g_a)
std::cout << t.a << " ";
std::cout << std::endl;
}
It's not about the lambda function but rather about the vector that reallocates its memory. You can ammend this with std::vector::reserve.
int main() {
g_a.reserve(10);
^^^^^^^^^^^^^^^^
std::cout << "emplace_back:\n";
g_a.emplace_back(1);
std::cout << "emplace_back in lambda:\n";
auto f1 = [](int x) { g_a.emplace_back(x); };
f1(2);
std::cout << "\nContents: ";
for (A const& t : g_a)
std::cout << t.a << " ";
std::cout << std::endl;
}
Live Demo