Re: rvalue reference factory?
{ text has been reformatted to ~70 chars per line. -mod }
Am Dienstag, 13. Mai 2014 21:50:02 UTC+2 schrieb Daniel Kr?gler:
Understandeably. Your code attempts to return the reference to an object
with local storage duration, which is undefined behaviour, because that
object is already destroyed after the function return. This problem is
not specific to rvalue-references but to references or pointers in
general.
This hint helped me to change the code and see it (see below).
I was thinking an rvalue reference variable on the stack can be
used as a storage(!) target for a final std::move() of a factory
function - but this was wrong.
As you said: it's just a reference.
Please explain what you actually try to achieve.
I have a factory class that produces *ptr for allocated objects, that
have to be deleted by the caller. You know this requires your object
class to be able to be allocated in the heap. But some class - for
whatever reason - could prevent to be allocated in the heap, but allow
allocation on the stack only. I was thinking rvalue references could
be used to create objects on the stack (without copying - some classes
don't support copying).
It was more or less an exercise for rvalue references.
I was thinking that i somehow can store the std::move(...) return value
of a function in a BaseClass variable. But any target has to be
specific, because i need to use a move constructor of the specific
(derived) class. Unfortunately i can't return it as a base class and
use it polymorphically. But as the move constructor is more or less
a convention for destructive read on a source as a way to avoid copying
i don't see a technical reason to not have this option.
best regards,
Frank
---- changed example test.cc ----------------------
#include <string>
#include <iostream>
#include <stdexcept>
#include <memory>
struct Tracker
{
std::string _id;
Tracker(std::string const &id)
: _id(id)
{
std::cout << "track[" << id << "] start..." << std::endl;
}
~Tracker()
{
std::cout << "... track[" << _id << "] end" << std::endl;
}
};
class BaseClass
{
public:
BaseClass()
{
std::cout << "BaseClass c'tor" << std::endl;
};
BaseClass(BaseClass && rhs)
{
std::cout << "BaseClass move c'tor" << std::endl;
};
virtual ~BaseClass()
{
std::cout << "BaseClass d'tor" << std::endl;
};
virtual std::string GetId(void) const = 0;
};
class Derived1 : public BaseClass
{
public:
Derived1()
: BaseClass()
{
std::cout << "Derived1 c'tor" << std::endl;
};
Derived1(Derived1 && rhs)
: BaseClass(std::move(rhs))
{
std::cout << "Derived1 move c'tor" << std::endl;
}
~Derived1()
{
std::cout << "Derived1 d'tor" << std::endl;
};
virtual std::string GetId(void) const
{
return std::string("Derived1");
}
static Derived1 && build(void)
{
Tracker tracker("Derived1::build()");
return std::move(Derived1());
}
};
class Derived2 : public BaseClass
{
public:
Derived2()
: BaseClass()
{
std::cout << "Derived2 c'tor" << std::endl;
};
Derived2(Derived2 && rhs)
: BaseClass(std::move(rhs))
{
std::cout << "Derived2 move c'tor" << std::endl;
}
~Derived2()
{
std::cout << "Derived2 d'tor" << std::endl;
};
virtual std::string GetId(void) const
{
return std::string("Derived2");
}
static Derived2 && build(void)
{
return std::move(Derived2());
}
};
class Factory
{
public:
static BaseClass && build(std::string const & id)
{
Tracker tracker("Factory::build()");
if (0 == id.compare("Derived1"))
{
return std::move(Derived1::build());
}
else if (0 == id.compare("Derived2"))
{
return std::move(Derived2::build());
}
else
{
throw std::runtime_error("invalid type");
}
}
};
int main(int argc, char** argv)
{
try
{
#if 0
// this does not work
BaseClass && baseClass(Factory::build("Derived1"));
BaseClass const * ptr = &baseClass;
#elif 0
// this does not work either
Derived1 && derived1(Derived1::build());
BaseClass * ptr = &derived1;
#else
// this works
Derived1 derived1(Derived1::build());
BaseClass * ptr = &derived1;
#endif
std::cout << "trying to get ID..." << std::endl;
std::cout << "ID = " << ptr->GetId() << std::endl;
}
catch (std::exception & e)
{
std::cerr << "exception: " << e.what() << std::endl;
}
return 0;
}
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]