Here is JLBorges' elegant vout function that randomizes the cout function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
#include <iostream>
#include <cstdlib>
#include <ctime>
template < typename STREAM_TYPE, STREAM_TYPE& stm >
struct basic_vstream
{
template< typename T >
static STREAM_TYPE& print_any( const T& v ) { return stm << v ; }
template< typename FIRST, typename... REST >
static STREAM_TYPE& print_any( const FIRST& first, const REST&... rest )
{
const std::size_t n = sizeof...(rest) + 1 ;
if( std::rand() % n == 0 ) return stm << first ;
else return print_any(rest...) ;
}
template < typename... ARGS >
const basic_vstream& operator() ( const ARGS&... args ) const
{
print_any(args...) ;
return *this ;
}
// etc
const basic_vstream& operator() ( STREAM_TYPE& (*manip)( STREAM_TYPE& ) ) const
{ stm << manip ; return *this ; }
// other manipulators
};
using vstream = basic_vstream< std::ostream, std::cout > ;
const vstream vout ;
int main()
{
std::srand( std::time(nullptr) ) ;
const char space = ' ' ;
for( int i=0 ; i < 10 ; ++i )
vout( "Attention!", "Hear this!", "Alert!" ) (space) ("We must leave!", "We're out of money!") (std::endl) ;
std::cin.get();
}
|
Anyone have any idea how to nest the vout function in the following sense?
1 2 3 4
|
vout( "Attention!", "Hear this!", "Alert!" ) (space)
( "We must leave!", "We're out of money!",
( "I hate", "We detest", "I loathe" ) (space)
( "you!", ("them", "these guys", "those people")('.', '!')) );
|
In this example, one of "Attention!", "Hear this!", "Alert!" is randomly chosen, then space is chosen, and then the nested part:
Either "We must leave!" is chosen, or "We're out of money!" is chosen, or
( "I hate", "We detest", "I loathe" ) (space) ( "you!", ("them", "these guys", "those people")('.', '!'))
is chosen.
I guess the line 'if( std::rand() % n == 0 ) return stm << first ;'
needs to be modified if 'first' is itself of type basic_vstream (e.g. calling itself recursively even though first is only one argument because first is itself of form args...).
Just to note:
vout( "Attention!", ( "I hate you", "We detest you", "I loathe you" ) ) (std::endl) ;
compiles (though the randomization with args... is not right, always displaying "I loathe you"), but
vout( "Attention!", ( "I hate you", "We detest you", "I loathe you" ) ('.') (std::endl) ;
does not compile.
Ideally the solution should allow any depth of nestings, and no nestings needs to work as a special case.