Dangers of storing rvalue references in templates - c++

Consider following piece of code:
#include <functional>
template<class T>
class factory {
public:
factory(T &&t) : t_(std::forward<T>(t)) {}
private:
T &&t_;
};
template<class T>
factory<T> make_factory(T &&t) {
return factory<T>(std::forward<T>(t));
}
int main(){
int i = 3;
auto bar = make_factory(i); //now it will store int &
auto foo = make_factory(5); //now will store int &&
return 0;
}
This is of course simplification of code but shows my general idea - I am considering storing references to rvalues. As far as I know in the first case the deduced type will be int & so the factory will be valid until leaving of the scope (due to reference collapsing). My questions are
Is the foo object causing undefined behaviour?
If not, for how long is the stored rvalue reference valid (I mean, what's its scope)?
Are there any caveats that I am missing?
EDIT:
I thought this is enough but I see I have to clarify. I want to achieve something like this:
template<class T>
class factory {
public:
factory(T &&t) : t_(std::forward<T>(t)) {}
auto make() const & {
return wrap(t_);
}
auto make() && {
return wrap(/*what here, move(t_), forward<T>(t_) ?*/);
}
private:
T t_;//or maybe T&& here?
};
I do not want to copy the member unless I really have to. I would like to do something like forwarding through the factory class.

Generally do this:
template<class T>
class factory {
public:
factory(T &&t) : t_(std::forward<T>(t)) {}
private:
T t_; // could be a lvalue ref
};
and it just works. Really. Yep, that case too.
Rvalues should not outlive their enclosing statement; so your make factory should not return a struct containing an rvalue ref.

Related

Is there a way to simultaneously assign a type to multiple templates in C++?

This question is based on the example code below, which is inspired by Sean Parent's talk.
The goal of the code below is to provide an object wrapper similar to boost::any. I wrote this code to educate myself of type erasure. So, there is no practical uses this code intends (considering there is already boost::any).
class ObjWrap {
public:
template <typename T>
ObjWrap(T O) : Self(new Obj<T>(std::move(O))) {}
template <typename T>
friend typename T * getObjPtr(ObjWrap O) {
return static_cast<T*>(O.Self->getObjPtr_());
}
private:
struct Concept {
virtual ~Concept() = 0;
virtual void* getObjPtr_() = 0;
};
template <typename T>
struct Obj : Concept {
Obj(T O) : Data(std::move(O)) {}
void* getObjPtr_() { return static_cast<void*>(&Data); }
T Data;
};
std::unique_ptr<Concept> Self;
};
Before I can really ask my question, let's examine the code in the following aspects:
Concept::getObjPtr_ returns void* because a) Concept cannot be a template otherwise unique_ptr<Concept> Self would not work; b) void* is the only way I know how to return Obj::Data in a type-agnostic way in C++. Please correct me if this is wrong...
T * getObjPtr(ObjWrap O) is a template that needs instantiation separately from the ObjWrap constructor.
The use of ObjWrap basically includes: a) make a new ObjWrap over an existing object; b) retrieve the underlying object given an ObjWrap. For example:
ObjWrap a(1);
ObjWrap b(std::string("b"));
int* p_a = getObjPtr<int>(a);
std::string* p_b = getObjPtr<std::string>(b);
This works but it is obvious that getObjPtr<int>(b) does not work as intended.
So, my question is:
Is there a way to fix the above code so that we can simply use int* p_a = getObjPtr(a) and std::string* p_b = getObjPtr(b) or better yet auto p_a = getObjPtr(a) and auto p_b = getObjPtr(b)? In other words, is there a way in C++ to instantiate two templates at the same time (if so, we can instantiate the ObjWrap constructor and T* getObjPtr(ObjWrap) at compile time of a ObjWrap object, e.g., ObjWrap a(1))?
Edit 1:
Making ObjWrap a templated class does not help since it defeats the purpose of type erasure.
template <typename T>
class ObjWrap {
/* ... */
};
ObjWrap<int> a(1); // this is no good for type erasure.
Edit 2:
I was reading the code and realize that it can be modified to reflect the idea a little better. So, please also look at the following code:
class ObjWrap {
public:
template <typename T>
ObjWrap(T O) : Self(new Obj<T>(std::move(O))) {}
template <typename T>
T * getObjPtr() {
return static_cast<T*>(Self->getObjPtr_());
}
private:
struct Concept {
virtual ~Concept() = 0;
virtual void* getObjPtr_() = 0;
};
template <typename T>
struct Obj : Concept {
Obj(T O) : Data(std::move(O)) {}
void* getObjPtr_() { return static_cast<void*>(&Data); }
T Data;
};
std::unique_ptr<Concept> Self;
};
int main() {
ObjWrap a(1);
ObjWrap b(std::string("b"));
int* p_a = a.getObjPtr<int>();
std::string* p_b = b.getObjPtr<std::string>();
std::cout << *p_a << " " << *p_b << "\n";
return 0;
}
The main difference between this version of the code versus the one above is that T * getObjPtr() is a member function that is encapsulated by the ObjWrap object.
Edit 3:
My question regarding type erasure is answered by accepted answer. However, the question on simultaneous type instantiation to multiple templates is yet to be answered. My guess is currently C++ does not allow it but it would be nice to hear from people with more experience on that.
There are a few things that may help.
First thing to say is that if Obj ever needs to expose the address of the object, it's not Sean Parent's 'inheritance is the root of all evil' type-erasing container.
The trick is to ensure that the interface of Obj offers all semantic actions and queries the wrapper will ever need.
In order to provide this, it's often a reasonable idea to cache the address of the object and its type_id in the concept.
Consider the following updated example, in which there is one public method - operator==. The rule is that two Objs are equal if they contain the same type of object and those objects compare equal.
Note that the address and type_id:
1) are implementation details and not exposed on the interface of Obj
2) are accessible without virtual calls, which short-circuits the not-equal case.
#include <memory>
#include <utility>
#include <typeinfo>
#include <utility>
#include <cassert>
#include <iostream>
class ObjWrap
{
public:
template <typename T>
ObjWrap(T O) : Self(new Model<T>(std::move(O))) {}
// objects are equal if they contain the same type of model
// and the models compare equal
bool operator==(ObjWrap const& other) const
{
// note the short-circuit when the types are not the same
// this means is_equal can guarantee that the address can be cast
// without a further check
return Self->info == other.Self->info
&& Self->is_equal(other.Self->addr);
}
bool operator!=(ObjWrap const& other) const
{
return !(*this == other);
}
friend std::ostream& operator<<(std::ostream& os, ObjWrap const& o)
{
return o.Self->emit(os);
}
private:
struct Concept
{
// cache the address and type here in the concept.
void* addr;
std::type_info const& info;
Concept(void* address, std::type_info const& info)
: addr(address)
, info(info)
{}
virtual ~Concept() = default;
// this is the concept's interface
virtual bool is_equal(void const* other_address) const = 0;
virtual std::ostream& emit(std::ostream& os) const = 0;
};
template <typename T>
struct Model : Concept
{
Model(T O)
: Concept(std::addressof(Data), typeid(T))
, Data(std::move(O)) {}
// no need to check the pointer before casting it.
// Obj takes care of that
/// #pre other_address is a valid pointer to a T
bool is_equal(void const* other_address) const override
{
return Data == *(static_cast<T const*>(other_address));
}
std::ostream& emit(std::ostream& os) const override
{
return os << Data;
}
T Data;
};
std::unique_ptr<Concept> Self;
};
int main()
{
auto x = ObjWrap(std::string("foo"));
auto y = ObjWrap(std::string("foo"));
auto z = ObjWrap(int(2));
assert(x == y);
assert(y != z);
std::cout << x << " " << y << " " << z << std::endl;
}
http://coliru.stacked-crooked.com/a/dcece2a824a42948
(etc. etc.) Please correct me if this is wrong...
Your premise is wrong at least in principle, if not also in practice. You're insisting on making getObjPtr() a virtual method, and using an abstract base class. But - you've not established this is necessary. Remember - using virtual methods is expensive! Why should I pay for virtuals just to get type erasure?
Is there a way to fix the above code so that we can simply use int* p_a = getObjPtr(a)
Take Sean Parent's talk title to heart (as opposed to the fact that he does use inheritance in the talk), drop the inheritance and the answer should be Yes. Edit: It's sufficient for the code that erases the type and the code that un-erases the type to know what the type is - as long as you don't need to act on the type-erased data in a type-specific way. In Sean Parent's talk, you need to be able to make non-trivial copies of it, to move it, to draw it etc. With std::any/boost::any you might need copying and moving, which may require virtuals - but that's the most general use case.
Even std::any limits what you can and can't do, as is discussed in this question:
why doesn't std::any_cast support implicit conversion?

Create library to override operator*() of iterator - risk dangling pointer

I am trying to create my own boost::adaptors::transformed.
Here is the related boost code.
Here is its usage (modified from a SO answer by LogicStuff):-
C funcPointer(B& b){
//"funcPointer" is function convert from "B" to "C"
return instance-of-C
}
MyArray<B> test; //<-- any type, must already have begin() & end()
for(C c : test | boost::adaptor::transformed(funcPointer)) {
//... something ....
}
The result will be the same as :-
for(auto b : test) {
C c = funcPointer(b);
//... something ...
}
My Attempt
I created CollectAdapter that aim to work like boost::adaptor::transformed.
It works OK in most common cases.
Here is the full demo and back up. (same as below code)
The problematic part is CollectAdapter - the core of my library.
I don't know whether I should cache the collection_ by-pointer or by-value.
CollectAdapter encapsulates underlying collection_ (e.g. pointer to std::vector<>) :-
template<class COLLECTION,class ADAPTER>class CollectAdapter{
using CollectAdapterT=CollectAdapter<COLLECTION,ADAPTER>;
COLLECTION* collection_; //<---- #1 problem? should cache by value?
ADAPTER adapter_; //<---- = func1 (or func2)
public: CollectAdapter(COLLECTION& collection,ADAPTER adapter){
collection_=&collection;
adapter_=adapter;
}
public: auto begin(){
return IteratorAdapter<
decltype(std::declval<COLLECTION>().begin()),
decltype(adapter_)>
(collection_->begin(),adapter_);
}
public: auto end(){ ..... }
};
IteratorAdapter (used above) encapsulates underlying iterator, change behavior of operator* :-
template<class ITERATORT,class ADAPTER>class IteratorAdapter : public ITERATORT {
ADAPTER adapter_;
public: IteratorAdapter(ITERATORT underlying,ADAPTER adapter) :
ITERATORT(underlying),
adapter_(adapter)
{ }
public: auto operator*(){
return adapter_(ITERATORT::operator*());
}
};
CollectAdapterWidget (used below) is just a helper class to construct CollectAdapter-instance.
It can be used like:-
int func1(int i){ return i+10; }
int main(){
std::vector<int> test; test.push_back(5);
for(auto b:CollectAdapterWidget::createAdapter(test,func1)){
//^ create "CollectAdapter<std::vector<int>,func1>" instance
//here, b=5+10=15
}
}
Problem
The above code works OK in most cases, except when COLLECTION is a temporary object.
More specifically, dangling pointer potentially occurs when I create adapter of adapter of adapter ....
int func1(int i){ return i+10; }
int func2(int i){ return i+100; }
template<class T> auto utilityAdapter(const T& t){
auto adapter1=CollectAdapterWidget::createAdapter(t,func1);
auto adapter12=CollectAdapterWidget::createAdapter(adapter1,func2);
//"adapter12.collection_" point to "adapter1"
return adapter12;
//end of scope, "adapter1" is deleted
//"adapter12.collection_" will be dangling pointer
}
int main(){
std::vector<int> test;
test.push_back(5);
for(auto b:utilityAdapter(test)){
std::cout<< b<<std::endl; //should 5+10+100 = 115
}
}
This will cause run time error. Here is the dangling-pointer demo.
In the real usage, if the interface is more awesome, e.g. use | operator, the bug will be even harder to be detected :-
//inside "utilityAdapter(t)"
return t|func1; //OK!
return t|func1|func2; //dangling pointer
Question
How to improve my library to fix this error while keeping performance & robustness & maintainablilty near the same level?
In other words, how to cache data or pointer of COLLECTION (that can be adapter or real data-structure) elegantly?
Alternatively, if it is easier to answer by coding from scratch (than modifying my code), go for it. :)
My workarounds
The current code caches by pointer.
The main idea of workarounds is to cache by value instead.
Workaround 1 (always "by value")
Let adapter cache the value of COLLECTION.
Here is the main change:-
COLLECTION collection_; //<------ #1
//changed from .... COLLECTION* collection_;
Disadvantage:-
Whole data-structure (e.g. std::vector) will be value-copied - waste resource.
(when use for std::vector directly)
Workaround 2 (two versions of library, best?)
I will create 2 versions of the library - AdapterValue and AdapterPointer.
I have to create related classes (Widget,AdapterIterator,etc.) as well.
AdapterValue - by value. (designed for utilityAdapter())
AdapterPointer - by pointer. (designed for std::vector)
Disadvantage:-
Duplicate code a lot = low maintainability
Users (coders) have to be very conscious about which one to pick = low robustness
Workaround 3 (detect type)
I may use template specialization that do this :-
If( COLLECTION is an "CollectAdapter" ){ by value }
Else{ by pointer }
Disadvantage:-
Not cooperate well between many adapter classes.
They have to recognize each other : recognized = should cache by value.
Sorry for very long post.
I personally would go with template specialisation – however, not specialise the original template, but a nested class instead:
template<typename Collection, typename Adapter>
class CollectAdapter
{
template<typename C>
class ObjectKeeper // find some better name yourself...
{
C* object;
public:
C* operator*() { return object; };
C* operator->() { return object; };
};
template<typename C, typename A>
class ObjectKeeper <CollectAdapter<C, A>>
{
CollectAdapter<C, A> object;
public:
CollectAdapter<C, A>* operator*() { return &object; };
CollectAdapter<C, A>* operator->() { return &object; };
};
ObjectKeeper<Collection> keeper;
// now use *keeper or keeper-> wherever needed
};
The outer class then covers both cases by just always using pointers while the nested class hides the differences away.
Sure, incomplete (you yet need to add appropriate constructors, for instance, both to outer and inner class), but it should give you the idea...
You might even allow the user to select if she/he wants to copy:
template<typename Collection, typename Adapter, bool IsAlwaysCopy = false>
class CollectAdapter
{
template<typename C, bool IsCopy>
class ObjectWrapper // find some better name yourself...
{
C* object;
public:
C* operator*() { return object; };
C* operator->() { return object; };
};
template<typename C>
class ObjectWrapper<C, true>
{
C object;
public:
C* operator*() { return &object; };
C* operator->() { return &object; };
};
// avoiding code duplication...
template<typename C, bool IsCopy>
class ObjectKeeper : public ObjectWrapper<C, IsCopy>
{ };
template<typename C, typename A, bool IsCopy>
class ObjectKeeper <CollectAdapter<C, A>, IsCopy>
: public ObjectWrapper<CollectAdapter<C, A>, true>
{ };
ObjectKeeper<Collection> keeper;
};
In my indexed_view I store the value of the collection if it is an rvalue, and store a reference if it is an lvalue. You could do the same here: overload your operator| for both rvalues and lvalues.
template<typename Collection,typename Filter>
auto operator|(Collection&& collection,Filter filter){
return create_adapter_for_rvalue_collection(collection,filter);
}
template<typename Collection,typename Filter>
auto operator|(Collection const& collection,Filter filter){
return create_adapter_for_const_lvalue_collection(collection,filter);
}
template<typename Collection,typename Filter>
auto operator|(Collection & collection,Filter filter){
return create_adapter_for_non_const_lvalue_collection(collection,filter);
}

Managing C++ Delegate lifetime

I came across the following blog post which explains how to build C++ delegates using variadic templates: http://blog.coldflake.com/posts/2014-01-12-C++-delegates-on-steroids.html
I'm reproducing the Delegate class in the post here:
template<typename return_type, typename... params>
class Delegate
{
typedef return_type (*Type)(void* callee, params...);
public:
Delegate(void* callee, Type function)
: fpCallee(callee)
, fpCallbackFunction(function) {}
template <class T, return_type (T::*TMethod)(params...)>
static Delegate from_function(T* callee)
{
Delegate d(callee, &methodCaller<T, TMethod>);
return d;
}
return_type operator()(params... xs) const
{
return (*fpCallbackFunction)(fpCallee, xs...);
}
private:
void* fpCallee;
Type fpCallbackFunction;
template <class T, return_type (T::*TMethod)(params...)>
static return_type methodCaller(void* callee, params... xs)
{
T* p = static_cast<T*>(callee);
return (p->*TMethod)(xs...);
}
};
And an example of how to use the class is given here:
class A
{
public:
int foo(int x)
{
return x*x;
}
int bar(int x, int y, char a)
{
return x*y;
}
};
int main()
{
A a;
auto d = Delegate<int, int>::from_function<A, &A::foo>(&a);
auto d2 = Delegate<int, int, int, char>::from_function<A, &A::bar>(&a);
printf("delegate with return value: d(42)=%d\n", d(42));
printf("for d2: d2(42, 2, 'a')=%d\n", d2(42, 2, 'a'));
return 0;
}
The technique is pretty cool, except that I would also like to have the Delegate class manage the callee's lifetime (in other words I would like to instantiate A on the heap and when the Delegate instance is deleted or goes out of scope, it should also be able to delete the callee (the A instance in this case)). Is there a simple way of doing this? Am I missing something? One solution would be to also pass a deleter object, which would cast the void* fpCallee to the correct type and then call delete ont it. Is there a better solution for this?
You could use shared_ptr<void> to store the callee instead of void* (see this question for why this doesn't cause delete problems; thanks Kindread). This would require you to keep every callee in a shared_ptr, but if you don't mind that, it would solve your problem.
And while this isn't an answer to the question, you could accomplish pretty much the same thing using a lambda instead of Delegate:
auto a = std::make_shared<A>();
auto d = [a](int x) { a->foo(x); };

gcnew operator for generic type

I have the following simple class
generic<typename T> where T:IDbConnection ref class CDbConnection
{
private:
IDbConnection^m_db;
ConnectionState^ m_originalConnState;
public:
CDbConnection();
bool Connect(String ^ connStr);
bool Exists(int id);
auto GetAllData(String^ tableStr);
~CDbConnection();
!CDbConnection();
};
and here is my constructor
generic<typename T> CDbConnection<T>::CDbConnection()
{
m_db=gcnew T();
m_originalConnState=m_db->State;
}
But the compiler complains <1> the gcnew T() can't be used for generic type
<2> auto key in use is wrong as the function expects a trailing return type
Thank you for your reading and replies
I forgot this
where T:IDbConnection, gcnew()
which is exactly the same as C# generics
to get rid of the gcnew error as stated above.
In order to achieve genericity, you must change your class definition to
generic<typename T> where T:IDbConnection ref class CDbConnection
{
private:
T m_db;
ConnectionState^ m_originalConnState;
public:
CDbConnection();
bool Connect(String ^ connStr);
bool Exists(int id);
auto GetAllData(String^ tableStr);
~CDbConnection();
!CDbConnection();
};
As you are already constraining your T to be at least IDbConnection it can't be anything else.
Then your constructor
generic<typename T> CDbConnection<T>::CDbConnection()
{
m_originalConnState=m_db.State;
}
should work like you intended.
EDIT
It seems you cannot declare a reference to a generic. If you assign the object to the stack it will work.
See this entry.
// C3229.cpp
// compile with: /clr /c
generic <class T>
ref class C {
T^ t; // C3229
};
// OK
generic <class T>
ref class D {
T u;
};

Template type deduction with a non-copyable class

Suppose I have an autolocker class which looks something like this:
template <T>
class autolocker {
public:
autolocker(T *l) : lock(l) {
lock->lock();
}
~autolocker() {
lock->unlock();
}
private:
autolocker(const autolocker&);
autolocker& operator=(const autolocker&);
private:
T *lock;
};
Obviously the goal is to be able to use this autolocker with anything that has a lock/unlock method without resorting to virtual functions.
Currently, it's simple enough to use like this:
autolocker<some_lock_t> lock(&my_lock); // my_lock is of type "some_lock_t"
but it is illegal to do:
autolocker lock(&my_lock); // this would be ideal
Is there anyway to get template type deduction to play nice with this (keep in my autolocker is non-copyable). Or is it just easiest to just specify the type?
Yes you can use the scope-guard technique
struct autolocker_base {
autolocker_base() { }
protected:
// ensure users can't copy-as it
autolocker_base(autolocker_base const&)
{ }
autolocker_base &operator=(autolocker_base const&)
{ return *this; }
};
template <T>
class autolocker : public autolocker_base {
public:
autolocker(T *l) : lock(l) {
lock->lock();
}
autolocker(const autolocker& o)
:autolocker_base(o), lock(o.lock)
{ o.lock = 0; }
~autolocker() {
if(lock)
lock->unlock();
}
private:
autolocker& operator=(const autolocker&);
private:
mutable T *lock;
};
Then write a function creating the autolocker
template<typename T>
autolocker<T> makelocker(T *l) {
return autolocker<T>(l);
}
typedef autolocker_base const& autolocker_t;
You can then write it like this:
autolocker_t lock = makelocker(&my_lock);
Once the const reference goes out of scope, the destructor is called. It doesn't need to be virtual. At least GCC optimizes this quite well.
Sadly, this means you have to make your locker-object copyable since you need to return it from the maker function. But the old object won't try to unlock twice, because its pointer is set to 0 when it's copied, so it's safe.
Obviously you can't get away with autolocker being a template, because you want to use it as a type, and templates must be instantiated in order to obtain types.
But type-erasure might be used to do what you want. You turn the class template into a class and its constructor into a member template. But then you'd have to dynamically allocate an inner implementation object.
Better, store a pointer to a function that performs the unlock and let that function be an instance of a template chosen by the templatized constructor. Something along these lines:
// Comeau compiles this, but I haven't tested it.
class autolocker {
public:
template< typename T >
autolocker(T *l) : lock_(l), unlock_(&unlock<T>) { l->lock(); }
~autolocker() { unlock_(lock_); }
private:
autolocker(const autolocker&);
autolocker& operator=(const autolocker&);
private:
typedef void (*unlocker_func_)(void*);
void *lock_;
unlocker_func_ unlock_;
template <typename T>
static void unlock(void* lock) { ((T*)lock)->unlock(); }
};
I haven't actually tried this and the syntax might be wrong (I'm not sure how to take the address of a specific function template instance), but I think this should be doable in principle. Maybe someone comes along and fixes what I got wrong.
I like this a lot more than the scope guard, which, for some reason, I never really liked at all.
I think jwismar is correct and what you want is not possible with C++. However, a similar (not direct analogue) construct is possible with C++0x, using several new features (rvalues/moving and auto variable type):
#include <iostream>
template <typename T>
class autolocker_impl
{
public:
autolocker_impl(T *l) : lock(l) {
lock->lock();
}
autolocker_impl (autolocker_impl&& that)
: lock (that.lock)
{
that.lock = 0;
}
~autolocker_impl() {
if (lock)
lock->unlock();
}
private:
autolocker_impl(const autolocker_impl&);
autolocker_impl& operator=(const autolocker_impl&);
private:
T *lock;
};
template <typename T>
autolocker_impl <T>
autolocker (T* lock)
{
return autolocker_impl <T> (lock);
}
struct lock_type
{
void lock ()
{ std::cout << "locked\n"; }
void unlock ()
{ std::cout << "unlocked\n"; }
};
int
main ()
{
lock_type l;
auto x = autolocker (&l);
}
autolocker is a class template, not a class. Your "this would be ideal" is showing something that doesn't make sense in C++.