std :: array编译时间扣除

时间:2014-06-26 08:59:10

标签: c++ compile-time stdtuple

我有一段代码,我试图在给定等待数据类型的情况下自动解码缓冲区。数据表示为元组:

std::tuple<uint8_t, int32_t> data;
size_t bufferIndex;
IOBuffer::ConstSPtr buffer( std::make_shared<IOBuffer>(5) );

我也有元组heplers迭代元组并为每个元素执行一个仿函数:

//-------------------------------------------------------------------------
//
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);
    }
};

这是我的解码器函子:

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 the index in the 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 );
        }
    }
};

这就是调用代码的地方:

DecoderFunctor func;
IterateOverTuple( func, data, buffer, index );

因此,所有内容都适用于整数类型,它们可以完美地解码。但是,当我想尝试实现一种新的解码方法(对于数组)时,它没有编译:

std::tuple<std::array<uint16_t, 100>, std::array<uint8_t, 100>> data;

Here是错误(gcc-4.9)。

所以我不明白为什么会出现这个错误。由于测试std::is_integral<X>::value,数据不应在DecodeIntegral( x, buffer, index );对吗?

进行评估

请注意,这项工作正在进行中,因此肯定会出现一些错误和改进。谢谢你的帮助!

2 个答案:

答案 0 :(得分:5)

我承认我没有完成所有代码,但我相信你的问题是运行时与编译时条件。您不能使用运行时条件(如if (std::is_integral<:::>::value>)来防止编译时错误。

我理解DecodeIntegral仅在X确实是完整的时才可编辑。因此,您必须确保编译器(即实例化)永远不会看到使用非整数DecodeIntegral的{​​{1}}调用,而不仅仅是它永远不会出现在运行时。

看到函数X可以很容易地成为静态成员而没有任何语义变化,你可以使用“delegate to class”技巧来实现这一点。将DecodeIntegral移动到帮助程序类:

DecodeIntegral

根据评论中的请求添加

如果您需要多个鉴别器,请向帮助程序添加更多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 for 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); } }; 模板参数。如果您需要的鉴别器没有标准谓词,您可以自己编写。

(下面的例子假设鉴别器是独占的 - 最多只有一个是真的):

bool

答案 1 :(得分:1)

std::is_integral<X>::value评估为false,但这并不意味着下面的代码(DecodeIntegral( x, buffer, index );)被“跳过”。编译器也看到了这一行。所以,目前你有一个运行时条件,但实际上你需要一个编译时条件。

编辑:我只是想用一个简短的例子来编辑我的答案,但是Angew更快。看他的答案:)