forked from Alepha/Alepha
Fix forwarding the messages to the underlying functions.
If you take the address of the overriding function, it cannot be converted to the base class. So for all the "forward to underlying" set I have to make a base class with no overrides which forwards. Then the main stackable class can make any overrides it wants. I believe that this is still safe, since the base class knows the name to be virtual. So we're not taking the address of the impl function, but instead taking the index of the virtual function. If I'm wrong... I'll need a whole different approach here.
This commit is contained in:
@ -21,11 +21,63 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: StackableStreambuf_m
|
||||
struct PopStack{};
|
||||
}
|
||||
|
||||
struct StackableStreambufUnderlyingShim
|
||||
: protected virtual std::streambuf
|
||||
{
|
||||
private:
|
||||
virtual std::streambuf *getUnderlying() const= 0;
|
||||
|
||||
protected:
|
||||
// EEEW. But to sidestep/circumvent, all this below is necessary.
|
||||
auto
|
||||
forwardOverflow( const int ch ) const
|
||||
{
|
||||
int (std::streambuf::*ov)( int )= &StackableStreambufUnderlyingShim::overflow;
|
||||
return ( getUnderlying()->*ov )( ch );
|
||||
}
|
||||
|
||||
auto
|
||||
forwardUnderflow() const
|
||||
{
|
||||
int (std::streambuf::*uf)()= &StackableStreambufUnderlyingShim::underflow;
|
||||
return (getUnderlying()->*uf)();
|
||||
}
|
||||
|
||||
auto
|
||||
underlying_eback() const
|
||||
{
|
||||
char *(std::streambuf::*eb)() const= &StackableStreambufUnderlyingShim::eback;
|
||||
return (getUnderlying()->*eb)();
|
||||
}
|
||||
|
||||
auto
|
||||
underlying_gptr() const
|
||||
{
|
||||
char *(std::streambuf::*gp)() const= &StackableStreambufUnderlyingShim::gptr;
|
||||
return (getUnderlying()->*gp)();
|
||||
}
|
||||
|
||||
auto
|
||||
underlying_egptr() const
|
||||
{
|
||||
char *(std::streambuf::*egp)() const= &StackableStreambufUnderlyingShim::egptr;
|
||||
return (getUnderlying()->*egp)();
|
||||
}
|
||||
|
||||
void
|
||||
underlying_setg( char *const b, char *const g, char *const e )
|
||||
{
|
||||
void (std::streambuf::*sg)( char *, char *, char * )= &StackableStreambufUnderlyingShim::setg;
|
||||
return (getUnderlying()->*sg)( b, g, e );
|
||||
}
|
||||
};
|
||||
|
||||
struct exports::StackableStreambuf
|
||||
: virtual public std::streambuf
|
||||
: virtual public std::streambuf, virtual protected StackableStreambufUnderlyingShim
|
||||
{
|
||||
private:
|
||||
std::streambuf *underlying;
|
||||
std::streambuf *getUnderlying() const final { return underlying; }
|
||||
|
||||
public:
|
||||
~StackableStreambuf() override;
|
||||
@ -81,43 +133,6 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: StackableStreambuf_m
|
||||
// available.
|
||||
|
||||
std::streamsize xsputn( const char *data, std::streamsize amt ) override;
|
||||
|
||||
// EEEW. But to sidestep/circumvent, all this below is necessary.
|
||||
auto
|
||||
forwardUnderflow() const
|
||||
{
|
||||
int (std::streambuf::*uf)()= &StackableStreambuf::underflow;
|
||||
return (underlying->*uf)();
|
||||
}
|
||||
|
||||
auto
|
||||
underlying_eback() const
|
||||
{
|
||||
char *(std::streambuf::*eb)() const= &StackableStreambuf::eback;
|
||||
return (underlying->*eb)();
|
||||
}
|
||||
|
||||
auto
|
||||
underlying_gptr() const
|
||||
{
|
||||
char *(std::streambuf::*gp)() const= &StackableStreambuf::gptr;
|
||||
return (underlying->*gp)();
|
||||
}
|
||||
|
||||
auto
|
||||
underlying_egptr() const
|
||||
{
|
||||
char *(std::streambuf::*egp)() const= &StackableStreambuf::egptr;
|
||||
return (underlying->*egp)();
|
||||
}
|
||||
|
||||
void
|
||||
underlying_setg( char *const b, char *const g, char *const e )
|
||||
{
|
||||
void (std::streambuf::*sg)( char *, char *, char * )= &StackableStreambuf::setg;
|
||||
return (underlying->*sg)( b, g, e );
|
||||
}
|
||||
|
||||
void
|
||||
assume_underlying()
|
||||
{
|
||||
|
Reference in New Issue
Block a user