#include #include typedef boost::error_info error_string_entry; typedef boost::error_info error_int_entry; struct exception : virtual std::exception, virtual boost::exception { }; #ifndef WORKAROUND //I don't see why this code as is shouldn't just work #define THROW_EXCEPTION( cnd__, ... ) if( !(cnd__) ) { \ BOOST_THROW_EXCEPTION( exception() << boost::make_tuple( __VA_ARGS__ ) ); } #else //Instead I have to pathcup for the empty case, and surprisingly also the 1-length case #define THROW_EXCEPTION( cnd__, ... ) if( !(cnd__) ) { \ BOOST_THROW_EXCEPTION( error_with_tags( exception(), boost::make_tuple( __VA_ARGS__ ) ) ); } template struct error_with_tags_helper { E const & operator()( E const & x, T const & t ) { x << t; return x; } }; template struct error_with_tags_helper { E const & operator()( E const & x, T const & t ) { return x; } }; template struct error_with_tags_helper { E const & operator()( E const & x, T const & t ) { return x << boost::get<0>(t); } }; template inline E const & error_with_tags( E const & x, T const & t ) { error_with_tags_helper::value> et; return et(x,t); } #endif int main() { //Okay THROW_EXCEPTION( true, error_string_entry( "hello" ), error_int_entry( 123 ) ); //Fail -- zero parameters THROW_EXCEPTION( true ); //Fail -- one parameter THROW_EXCEPTION( true, error_string_entry( "hello" ) ); }