class MyClass {
public: MyClass(int a) : a(a) { }
int a;
};
#include <iostream>
void print(MyClass* a) { std::cout << a->a << std::endl; }
int main() {
print(&static_cast<MyClass&&>(MyClass(1337)));
return 0;
}
This doesn't work with GCC 4.6, while it used to work in a previous version.
Now it says: taking address of xvalue (rvalue reference).
Is there any way to securely pass the address of an rvalue to another function?
is: there is anyway to securely pass an rvalue reference (a.k.a. address of temporary) to another function without boringly storing it in a variable just to do that?
Yes, there is, like in the next example :
#include <iostream>
class MyClass {
public: MyClass(int a) : a(a) { }
int a;
};
void print(MyClass&& a) { std::cout << a.a << std::endl; }
int main() {
print( MyClass(1337) );
}
An rvalue does not necessarily have an address. However, there is a way to get the effect you want, by exploiting the fact that binding an rvalue to a reference forces it to be a temporary (which does have an address):
template<typename T> T *addressOfTemporary(T &&v) { return &v; }
Inside this function, v is an lvalue (despite being declared as T&&), so can have its address taken. You can use this function as follows:
class MyClass {
public: MyClass(int a) : a(a) { }
int a;
};
#include <iostream>
void print(MyClass* a) { std::cout << a->a << std::endl; }
int main() {
print(addressOfTemporary(MyClass(1337)));
return 0;
}
Note that the temporary's lifetime ends at the end of the full-expression (the print(...) expression, in this case), so you will need to be careful that the pointer is not used past that point.
If you don't particualrly need to print rvalues only, you can use a standard const reference instead:
class MyClass {
public: MyClass(int a) : a(a) { }
int a;
};
#include <iostream>
void print(const MyClass& a)
{ std::cout << a.a << std::endl; }
int main() {
print(MyClass(1337));
return 0;
}
Related
I wrote this piece of code:
class widget_12 {
public:
//reference qualifiers example
void dowork()&
{
std::cout << "*this is lvalue\n";
}; // this version of dowork applies when *this is lvalue
void dowork()&&
{
std::cout << "*this is rvlaue\n";
}; // -||- *this is rvalue
widget_12&& make_widget()
{
//TODO
}
};
I want to test reference qualifiers, therefore I need to create a function that will return the rvalue of widget_12, could you show me how to do it?
I am basically trying to make this call:
make_widget().dowork();
Were you trying something like this?
https://godbolt.org/z/TPEWe3eKv
#include <iostream>
class widget_12 {
public:
//reference qualifiers example
void dowork() &
{
std::cout << "*this is lvalue\n";
}; // this version of dowork applies when *this is lvalue
void doword() &&
{
std::cout << "*this is rvlaue\n";
}; // -||- *this is rvalue
static widget_12 make_widget()
{
return widget_12();
}
};
int main()
{
widget_12 w;
w.dowork();
//w.doword(); // error
widget_12::make_widget().doword();
//widget_12::make_widget().dowork(); // error
return 0;
}
When f is called, a is already "destructed". Is it safe to use it this way? How does it work?
std::function<void()> f;
{
int a = some_calc();
f = [=] { std::cout << a << std::endl; }
}
f();
Is it safe to use it this way?
Yes
How does it work?
The closure object created by that lambda expression has int a as a data member, copy-initialised from the a in that scope.
Here is conceptually what is going on:
#include <functional>
#include <iostream>
int some_calc() {
// ...
return 42;
}
int main() {
std::function<void()> f;
{
int a = some_calc();
class Lambda {
private:
int a;
public:
Lambda(int const& _a) : a{_a} {}
void operator()() const { std::cout << a << std::endl; }
};
f = Lambda{a};
}
f();
}
I have a function func(std::optional<A>& a) and I want to call it using an instance of A like in this code:
#include <optional>
#include <iostream>
class A
{
public:
explicit A(int a) : m_a(a)
{}
~A() = default;
int get() { return m_a; }
A(const A&) = delete;
A(A&&) = delete;
A& operator=(const A&) = delete;
A& operator=(A&&) = delete;
private:
int m_a;
};
void func(std::optional<A>& a)
{
if (a.has_value()) {
std::cout << a->get() << std::endl;
} else {
std::cout << "no value" << std::endl;
}
}
int main() {
A a(5);
func(a);
}
As you can see, A does not allow for any copy or move operators. When I run this code I get
<source>:34:10: error: invalid initialization of reference of type 'std::optional<A>&' from
expression of type 'A'
My question is how can I pass a to func() and make the std::optional reference my object?
If that's not possible, I would still like to have a way to pass a to func() not using c-style pointers (func(A* a) for example)
If another layer of indirection is not a problem you can use a std::optional<std::reference_wrapper<A>> :
#include <functional>
//....
void func(const std::optional<std::reference_wrapper<A>>& a)
{
if (a.has_value()) {
std::cout << a->get().get() << std::endl;
} else {
std::cout << "no value" << std::endl;
}
}
int main() {
A a(5);
func(std::ref(a));
}
(I suppose the missing const was a typo, because it would be an error in your example too even if A could be moved or copied).
Note that this does meet your requirements: Pass a std::optional and not use raw pointers. However, it is a little weird to use a reference (instead of pointer) because it cannot be null and then wrap that into an optional to allow "null" values. Using a raw pointer seems to be the most simple and straight forward solution.
Note that raw pointers are not "c-style". What can be considered c-style and what should be avoided by all means is raw owning pointers. When you want to pass a parameter to a function, and the function does not interfere with ownership, and it can either have a value or not a value then a raw pointer is just fine. Just do
void func(A* a)
{
if (a) {
std::cout << a->get() << std::endl;
} else {
std::cout << "no value" << std::endl;
}
}
int main() {
A a(5);
func(&a);
}
#include <iostream>
using namespace std;
class armon {
int a;
int b;
public:
armon(int newA, int newB) : a(newA), b(newB) {}
armon setA(int newA) {
a = newA;
return *this;
}
armon setB(int newB) {
b = newB;
return *this;
}
void print(void) { cout << a << endl << b; }
};
int main() {
armon s(3, 5);
s.setA(8).setB(9);
s.print();
}
Why can't i just return the object with the this pointer to make
cascaded function calls?
Why do i need to return the reference of the object?
What would that even do?
Returning this pointer would be sufficient, too. However, the syntax of cascaded invocation would need to change in the middle of the chain:
s.setA(8)->setB(9)->setC(10);
This does not look consistent, so returning a reference is a better choice.
I have a type hierarchy similar to the code sample below, and I'm trying to instantiate them via the factory pattern (or, to be pedantic, rather the builder pattern, as my factory takes input from an XML document... but I digress).
However I try to do this, I'm running into problems which I suspect are due to either slicing, if I return by value, or to scoping, if I return by reference.
The below program, for instance, segfaults on the line a.doA() inside C::doStuff(). If I change the call to value_C_factory<C>() to ref_C_factory<C>() instead, I get a couple of warnings to the effect of "returning reference to temporary", but the program compiles, segfaults instead on b.doB() on the next line (without having printed anything from a.doA()...).
The backtrace from gdb looks like this - the second line is the one in my code referred to above
#0 0x00007ffff7dbddb0 in vtable for std::ctype<char> () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1 0x00000000004010e9 in C::doStuff (this=0x7fffffffdd00) at syntax.cpp:57
#2 0x0000000000400cf2 in main () at syntax.cpp:95
What is causing these segfaults? Is it, as I suspect, slicing/scoping in the value/reference case? If not, what is it? And most importantly, what is a good way to build my instances from the input data?
Code sample
The code below should compile and give the above behavior with e.g. GCC 4.8, using
gcc -g -Wall -std=c++11 -o test test.cpp (that's what I do, anyway).
#include <iostream>
#include <typeinfo>
class IA {
public:
virtual void doA() const = 0;
virtual ~IA() { }
};
class A : public IA {
private:
std::string atask;
public:
explicit A(const std::string &task) : atask(task) {
std::cout << "Created A with task " << atask << std::endl;
}
void doA() const {
std::cout << "I did A! " << atask << std::endl;
}
};
class IB {
public:
virtual void doB() const = 0;
virtual ~IB() { }
};
class B : public IB {
private:
std::string btask;
public:
explicit B(const std::string &task) : btask(task) {
std::cout << "Created B with task " << btask << std::endl;
}
void doB() const {
std::cout << "I did B! " << btask << std::endl;
}
};
class IC {
public:
void doStuff() const;
virtual ~IC() { }
};
class C : public IC {
private:
const IA &a;
const IB &b;
public:
C(const IA &a, const IB &b) : a(a), b(b) { }
void doStuff() const {
a.doA(); // with value factory method, segfault here
b.doB(); // with reference factory, segfault here instead
}
};
template<typename TA>
TA value_A_factory() {
return TA("a value");
}
template<typename TB>
TB value_B_factory() {
return TB("b value");
}
template<typename TC>
TC value_C_factory() {
return TC(value_A_factory<A>(), value_B_factory<B>());
}
template<typename TA>
const TA &ref_A_factory() {
return TA("a ref");
}
template<typename TB>
const TB &ref_B_factory() {
return TB("b ref");
}
template<typename TC>
const TC &ref_C_factory() {
const TC &c(ref_A_factory<A>(), ref_B_factory<B>());
return c;
}
int main() {
C c = value_C_factory<C>();
std::cout << typeid(c).name() << std::endl;
c.doStuff();
}
You have two problems, both caused by undefined behavior.
The first is that you can't return a reference to a local variable. Once the function returns and the local variable goes out of scope and is destructed, what does the returned reference then reference?
The other problem is that you store references to temporary values. When you create your C class like TC(value_A_factory<A>(), value_B_factory<B>()) the values returned by the value_X_factory functions are temporary, and will be destroyed once the complete expression (TC(...)) is done.
In
template<typename TA>
const TA &ref_A_factory() {
return TA("a ref");
}
returning a reference to a local variable is undefined behavior.
In
TC(value_A_factory<A>(), ...)
the lifetime of the value returned by value_A_factory will be the end of the expression TC(...). After that your references in C are dangling.
If you really want to use interfaces and factories for polymorphic types, there is no real alternative to dynamic memory allocation and some kind of ownership scheme. The simplest would be for C to simply assume ownership of its members and take care of their deletion.
#include <memory>
#include <cassert>
struct IA {
virtual void doA() const = 0;
virtual ~IA() { };
};
struct A : IA {
void doA() const override {}
};
struct C {
/* C assumes ownership of a. a cannot be null. */
C(IA* a) : a{a} { assert(a && "C(IA* a): a was null"); };
private:
std::unique_ptr<IA> a;
};
C factory() {
return C{new A};
}
int main()
{
C c = factory();
return 0;
}