c++ - std::array 编译时间扣除

标签 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 ); 中评估数据对吧?

请注意,这是一项正在进行的工作,因此肯定存在一些错误和需要改进的地方。并感谢您的帮助!

最佳答案

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

我明白了DecodeIntegral仅在 X 时可编译确实是不可或缺的。因此,您必须确保调用 DecodeIntegral与非积分 X永远不会被编译器看到(即实例化),而且不仅仅是它永远不会在运行时发生。

视作函数DecodeIntegral可以很容易地成为静态成员而无需任何语义更改,您可以使用“委托(delegate)给类”技巧来实现这一点。移动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帮助程序的模板参数。如果您需要的鉴别器没有标准谓词,您可以自己编写。

(下面的例子假设鉴别器是互斥的——至多有一个为真):

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

关于c++ - std::array 编译时间扣除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24426372/

相关文章:

c++ - 使用精神以替代方式解析结构时混淆输出

c++ - 为什么有些线程会延迟?

c++ - 单行 std::get std::index_sequence?

c++ - 为什么string stream operator<<会删除原来的值

c++ - float 不等式是否保证一致

java - Java 对于重载方法最具体的方法规则如何与多个参数一起工作?

c++ - 通过模板参数给定其长度,在编译时生成相同类型的 std::tuple

c++ - 将 std::tuple 转换为 std::set

c++ - 我如何防止工厂用户基于枚举调用错误的模板化或重载方法?

c++ - 如何在编译时确认自动推断类型的假设? (即 static_assert 样式