patterncppMinor
Is this a valid implementation of a 'future'?
Viewed 0 times
thisimplementationvalidfuture
Problem
I'm not very experienced in C++, but I am trying to circumvent a kind of 'constructor order' situation, where I have class A wants class B in its constructor, and vice versa. They don't really want eachother, but both implement an interface and need each other. I decided to give object A a future. Is this even remotely good practice in C++11?
I'm thinking that the code below should be fine - the shared_ptr simply serves to make the future passable by value - multiple future objects can represent the same 'future'. Since I am not experienced in C++, I'm not sure of any potential trouble. I think that I don't need to declare any special copy constructor or such, since I don't do any allocation and std::shared_ptr should be copy-constructible automatically.
What do you think?
UPDATE
The use case I have is a little more complicated than the above though. Here goes:
```
class view : public log_sink
{
view(tcp_client &client);
virtual sink members...
};
class tcp_client
{
tcp_client(log) //a sink should be provided before this, since it will do some logging.
};
class log
{
log(log_sink sink); //So this one needs view.
};
int main()
{
log log(view);
tcp_client client(log
I'm thinking that the code below should be fine - the shared_ptr simply serves to make the future passable by value - multiple future objects can represent the same 'future'. Since I am not experienced in C++, I'm not sure of any potential trouble. I think that I don't need to declare any special copy constructor or such, since I don't do any allocation and std::shared_ptr should be copy-constructible automatically.
What do you think?
#ifndef LIB_FUTURE
#define LIB_FUTURE
#include
#include
namespace lib {
template
class future
{
public:
future() : value_ptr(std::make_shared())
{ }
void set(TValue &value)
{
*value_ptr.get() = &value;
}
TValue& get()
{
assert_valid_access();
return **value_ptr;
}
TValue* operator->()
{
assert_valid_access();
return *value_ptr;
}
bool has_value()
{
return value_ptr.get() != nullptr;
}
private:
std::shared_ptr value_ptr;
void assert_valid_access()
{
if(!has_value())
throw std::runtime_error("Attempting to access a non-set value from a future");
}
};
}
#endifUPDATE
The use case I have is a little more complicated than the above though. Here goes:
```
class view : public log_sink
{
view(tcp_client &client);
virtual sink members...
};
class tcp_client
{
tcp_client(log) //a sink should be provided before this, since it will do some logging.
};
class log
{
log(log_sink sink); //So this one needs view.
};
int main()
{
log log(view);
tcp_client client(log
Solution
What's your inheritance relationship between A and B? If A is the parent of B, it's bad design if A needs to do ANYTHING with B in the constructor/destructor because B will not be valid until after A's construction.
If you require RAII design, look at lazy resource acquisition to avoid re-acquisition going up the constructor chain (vector).
Why do you want a smart pointer to a pointer. Smart pointers help you when there is no clear custodian of an instance (or shared primitive type), and you want to destroy an instance only when there are no more users of it. The way you are using the smart pointer means that only a memory location of a pointer is freed, not the memory of a type instance. Plus when you construct this class, the pointer held by the 'value_ptr' is random, which is bad.
I'm not sure where you're going with this 'future' class and how it solves your inter-dependance between A and B.
If A and B need a similar member, make them inherit from the same parent class. If you want to hide this 'shared' member or you want a pure-virtual interface, simply declare the interface as well as defining some sort of linking parent.
If A and B need access to the same instance of something, use a singleton that is inherited from a shared parent.
If you do need a shared instance, and you need to free any resources (IE files) held by the singleton, it's better to write an explicit free function. That way you will easily see where it's being cleaned up.
If you mean you want to avoid initializing a resource that's defined in a parent class, until your child class A or B does, perhaps look at making an explicit, polymorph function.
Hope that helps.
If you require RAII design, look at lazy resource acquisition to avoid re-acquisition going up the constructor chain (vector).
Why do you want a smart pointer to a pointer. Smart pointers help you when there is no clear custodian of an instance (or shared primitive type), and you want to destroy an instance only when there are no more users of it. The way you are using the smart pointer means that only a memory location of a pointer is freed, not the memory of a type instance. Plus when you construct this class, the pointer held by the 'value_ptr' is random, which is bad.
I'm not sure where you're going with this 'future' class and how it solves your inter-dependance between A and B.
If A and B need a similar member, make them inherit from the same parent class. If you want to hide this 'shared' member or you want a pure-virtual interface, simply declare the interface as well as defining some sort of linking parent.
If A and B need access to the same instance of something, use a singleton that is inherited from a shared parent.
If you do need a shared instance, and you need to free any resources (IE files) held by the singleton, it's better to write an explicit free function. That way you will easily see where it's being cleaned up.
If you mean you want to avoid initializing a resource that's defined in a parent class, until your child class A or B does, perhaps look at making an explicit, polymorph function.
Hope that helps.
Context
StackExchange Code Review Q#10618, answer score: 2
Revisions (0)
No revisions yet.