
Hi Eugene, --- Eugene Alterman <eugalt@verizon.net> wrote:
I will call this interfaces core_socket and stream_socket respectively. You always start with an object of a stream_socket class and then obtain a reference to core_socket from it.
Let us first start with a design that does not change the current interface of stream_socket. Define a new core_socket class template, and derive stream_socket from it adding the stream functionality. Then we can define lowest_layer_type as core_socket. This will solve the stream layering problem since having a reference to core_socket of a lower layer would not allow performing stream operations on it.
The next step would be to derive stream_socket privately from core_socket and provide a public member function returning a reference to core_socket. This would deal with any temptation to downcast a core_socket reference to stream_socket.
I think I understand what you want now, however I propose a few modifications, especially to preserve source compatibility with existing code and keep the common use cases simple. The core_socket template (don't particularly like the name, will think about it) could be used as the base for both stream_socket and datagram socket since they share everything except the read_some/write_some/send*/receive* functions. E.g.: template <typename Service> class core_socket { public: ... typedef core_socket<Service> lowest_layer_type; lowest_layer_type& lowest_layer() { return *this; } protected: service_type& service_; impl_type impl_; }; template <typename Service> class basic_stream_socket : private core_socket<Service> { public: ... typedef core_socket<Service> lowest_layer_type; lowest_layer_type& lowest_layer() { return *this; } }; template <typename Service> class basic_datagram_socket : private core_socket<Service> { public: ... typedef core_socket<Service> lowest_layer_type; lowest_layer_type& lowest_layer() { return *this; } }; The next_layer_type typedefs and next_layer() functions would be removed. The derived type should bring all public names from core_socket into its own public interface. Are using declarations OK in this case? If not, then via forwarding functions. That way existing uses of stream_socket continue to work as-is. Uses of stream templates would lose access to the underlying socket's I/O functions, as you want. Note there is still a way to circumvent the layering but it is now an explicit choice, e.g.: stream_socket inner(demuxer); buffered_stream<stream_socket&> outer(inner); Would anyone else care to comment on this modification? Cheers, Chris