# A reader and its associated writer for disjoint value access

While extending the functionality of my polymorphic_callable<> type, I designed a way to obtain a result through a reader type that is set by a writer type; this is very similar to what std::future<> and std::promise<> do, but in a non-multi-threaded way.

Since that other question is already very long, I've decided to post this question for a review that focuses on these simple classes.

reader<> semantics:

• It can only read from its contained value.
• It is a move-only type that can only be created by a writer<> instance's create_reader() member function.
• On destruction, its associated writer<>'s writing pointer is set to nullptr.

#ifndef READER_H

#include <utility>
#include <type_traits>

template<class> class writer;

template<class T>
{
public:
using value_type = T;

/**
* @brief sets the associated writer's pointer to nullptr
*/
{
writer_->value_ = nullptr;
}

/**
* @brief takes ownership of the contained value of the argument reader as
* if by move construction; associates the writer associated with the argument
*/
noexcept( std::is_nothrow_move_constructible<value_type>::value )
: value_{ std::move( rhs.value_ ) }
, writer_{ rhs.writer_ }
{
rhs.writer_->value_ = &value_;
}

/**
* @brief takes ownership of the contained value of the argument reader as
* if by move assignment; associates the writer associated with the argument
*/
noexcept( std::is_nothrow_move_assignable<value_type>::value )
{
writer_ = rhs.writer_;
value_ = std::move( rhs.value_ );
rhs.writer_->value_ = &value_;
}

/**
* @brief access the contained value
*/
value_type const& value() const noexcept
{
return value_;
}

private:
friend class writer<value_type>;

/**
* @brief constructs a reader and associates it with the parameter writer
*/
noexcept( std::is_nothrow_default_constructible<value_type>::value )
: value_{}
, writer_{ w }
{
w->value_ = &value_;
}

value_type value_;
writer<value_type>* writer_;
};

template<>
{
public:
using value_type = void;
};


## Writer

writer<> semantics:

• It is a friend class of the writer<> type.
• It has a pointer to its associated reader<> instance.
• It can write to its associated reader; if it's associated reader is not set, then writing does nothing. This is because a writer<> instance can outlive its associated reader<> instance.
• It can be queried to know whether it has an associated reader or not with the has_reader() member function.

writer.h

#ifndef WRITER_H
#define WRITER_H

#include <utility>
#include <type_traits>

template<class T>
class writer
{
public:
using value_type = T;

~writer() = default;

/**
* @brief constructs a writer with no assicated reader.
*/
constexpr writer() noexcept
: value_{ nullptr }
{}

writer( writer&& rhs ) = default;
writer( writer const& ) = default;
writer& operator=( writer&& ) = default;
writer& operator=( writer const& ) = default;

/**
* @brief sets the value associated with this writer; if there is no associated
* value, the function does nothing.
*/
template<class... Args>
void set_value( Args&&... args )
noexcept( std::is_nothrow_constructible<value_type, Args&&...>::value )
{
if ( value_ )
{
*value_ = value_type{ std::forward<Args>( args )... };
}
}

/**
* @brief creates a new reader and associates it to the reader.
*/
{
}

/**
* @brief indicates whether the reader has an associated writer or not.
* @return true if the reader has an associated writer, false otherwise.
*/
{
return static_cast<bool>( value_ );
}

private:

value_type* value_;
};

template<>
class writer<void>
{
public:
using value_type = void;

private:
};
#endif // WRITER_H


While the true use case of these types is found here, here is an usage sample:

#include <iostream>

int main()
{
writer<int> w;
w.set_value( 3 );
std::cout << r.value() << '\n';
}


struct updated_t
{
updated_t( writer<int>& wint, writer<std::string>& wstring )
{}

};

int main()
{
writer<int> wint;
writer<std::string> wstring;
updated_t updated{ wint, wstring };
while ( true )
{
/* write with wint, wstring */
/* rint and rstring get updated where ever they may be */
wint.set_value( 3 );
std::cout << updated.rint.value() << '\n';

wstring.set_value( "hello world\n" );
std::cout << updated.rstring.value() << '\n';

break;
}
}


I'm interested in a review on design and any other features that are missing or that could be added/improved.

You could make implicit conversion to bool for writer<> class, so it would be less cumbersome to use it. On the other hand, those who are not familiar with the internals might be surprised during their first use.
Since classes has explicit names, you could write operator(), since it is explicit that invoking it on reader<> object will perform read, and invoking it with parameter on writer<> object will perform writing.
The code uses circular references. I know that it greatly simplifies the implementation, but probably there is a better solution. I think that the problem leads to creation of raw memory class, which would be supplied into the polymorphic_callable<>. std::optional<> would be great idea too. When std::optional<> object will evaluate to true, it will mean that the function has been called and it properly finished execution. You could provide your own until C++17, since it is pretty trivial to write one.