c++ - std::array compile time deduction -
i have piece of code tried automatically decode buffer given awaited data types. data represented tuples:
std::tuple<uint8_t, int32_t> data; size_t bufferindex; iobuffer::constsptr buffer( std::make_shared<iobuffer>(5) );
i have tuple heplers iterate on tuples , execute functor each one:
//------------------------------------------------------------------------- // template <typename function, typename ...tuples, typename ...args> void iterateovertuple( function& f, std::tuple<tuples...>& t, args&... args ) { impl::iterateovertupleimpl<0, sizeof...(tuples), std::tuple<tuples...>>()( f, t, args... ); } //--------------------------------------------------------------------- // template <int i, size_t tsize, typename tuple> struct iterateovertupleimpl : public iterateovertupleimpl<i + 1, tsize, tuple> { template <typename function, typename ...args> void operator()( function& f, tuple& t, args&... args ) { f( std::get<i>(t), args... ); iterateovertupleimpl<i + 1, tsize, tuple>::operator()( f, t, args... ); } }; //--------------------------------------------------------------------- // template <int i, typename tuple> struct iterateovertupleimpl<i, i, tuple> { template <typename function, typename ...args> void operator()( function& f, tuple& t, args&... ) { cl::ignore(f); cl::ignore(t); } };
and here decoder functor:
struct decoderfunctor { template <typename x> void decodeintegral( x& x, const iobuffer::constsptr& buffer, size_t& index ) { if( std::is_same<x, uint8_t>::value ) { x = buffer->at(index); } else if( std::is_same<x, int8_t>::value ) { x = static_cast<int8_t>( buffer->at(index) ); } else if( std::is_same<x, uint16_t>::value ) { x = cl::byteconversion::ubytestouint16( ubytearray<2>{{ buffer->at(index + 0), buffer->at(index + 1) }} ); } else if( std::is_same<x, int16_t>::value ) { x = cl::byteconversion::ubytestoint16( ubytearray<2>{{ buffer->at(index + 0), buffer->at(index + 1) }} ); } else if( std::is_same<x, uint32_t>::value ) { x = cl::byteconversion::ubytestouint32( ubytearray<4>{{ buffer->at(index + 0), buffer->at(index + 1), buffer->at(index + 2), buffer->at(index + 3) }} ); } else if( std::is_same<x, int32_t>::value ) { x = cl::byteconversion::ubytestoint32( ubytearray<4>{{ buffer->at(index + 0), buffer->at(index + 1), buffer->at(index + 2), buffer->at(index + 3) }} ); } else if( std::is_same<x, uint64_t>::value ) { x = cl::byteconversion::ubytestouint64( ubytearray<8>{{ buffer->at(index + 0), buffer->at(index + 1), buffer->at(index + 2), buffer->at(index + 3), buffer->at(index + 4), buffer->at(index + 5), buffer->at(index + 6), buffer->at(index + 7) }} ); } else if( std::is_same<x, int64_t>::value ) { x = cl::byteconversion::ubytestoint64( ubytearray<8>{{ buffer->at(index + 0), buffer->at(index + 1), buffer->at(index + 2), buffer->at(index + 3), buffer->at(index + 4), buffer->at(index + 5), buffer->at(index + 6), buffer->at(index + 7) }} ); } // increment index in buffer index += sizeof(x); } template <typename x> void operator()( x& x, const iobuffer::constsptr& buffer, size_t& index ) { if( std::is_integral<x>::value ) { decodeintegral( x, buffer, index ); } } };
and code called:
decoderfunctor func; iterateovertuple( func, data, buffer, index );
so works fine integral types , decoded perfectly. when wanted try implement new decoding method (for arrays), didn't compile:
std::tuple<std::array<uint16_t, 100>, std::array<uint8_t, 100>> data;
here error (gcc-4.9).
so don't understand why error. because of test std::is_integral<x>::value
data should not evaluated in decodeintegral( x, buffer, index );
right ?
please not work in progress there few mistakes , improvements make. , thank !
i admit haven't gone through of code, believe issue runtime vs. compile-time conditions. cannot use run-time condition (like if (std::is_integral<:::>::value>)
prevent compile-time errors.
i understand decodeintegral
compilable when x
indeed integral. therefore, must make sure call decodeintegral
non-integral x
never seen compiler (i.e. instantiated), , not never occurs @ runtime.
seeing function decodeintegral
static member without change in semantics, can use "delegate class" trick achieve this. move decodeintegral
helper class:
template <bool integral> struct helper; template <> struct helper<true> { template <class x> static void decode( x& x, const iobuffer::constsptr& buffer, size_t& index ) { // old code of decodeintegral() goes here } }; template <> struct helper<false> { template <class x> static void decode( x& x, const iobuffer::constsptr& buffer, size_t& index ) { // code non-integral decoding goes here } }; struct decoderfunctor { template <typename x> void operator()( x& x, const iobuffer::constsptr& buffer, size_t& index ) { helper<std::is_integral<x>::value>::decode(x, buffer, index); } };
added based on request in comment
if need more 1 discriminator, add more bool
template parameters helper. if there no standard predicate discriminator need, can write own.
(the example below assumes discriminators exclusive - @ 1 true):
// two-discriminator helper template <bool integral, bool array> struct helper; template <> struct helper<true, false> { void decode() { /* integral decode */ } }; template <> struct helper<false, true> { void decode() { /* array decode */ } }; // custom predicate template <class t> struct isstdarray : std::false_type {}; template <class t, size_t n> struct isstdarray<std::array<t, n>> : std::true_type {}; // usage struct decoderfunctor { template <typename x> void operator()( x& x, const iobuffer::constsptr& buffer, size_t& index ) { helper< std::is_integral<x>::value, isstdarray<x>::value >::decode(x, buffer, index); } };
Comments
Post a Comment