[英]std::array compile time deduction
I have a piece of code that I tried to automatically decode a buffer given the awaited data types. 我有一段代码,我尝试在给定等待数据类型的情况下自动解码缓冲区。 The data are represented as tuples:
数据表示为元组:
std::tuple<uint8_t, int32_t> data;
size_t bufferIndex;
IOBuffer::ConstSPtr buffer( std::make_shared<IOBuffer>(5) );
I also have tuple heplers to iterate over the tuples and execute a functor for each one: 我也有元组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);
}
};
And here is my 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 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 );
}
}
};
And this is where the code is called: 这就是调用代码的地方:
DecoderFunctor func;
IterateOverTuple( func, data, buffer, index );
So everything works fine with integral types and they are decoded perfectly. 所以一切都可以使用整数类型工作,它们可以完美地解码。 However when I wanted to try to implement a new decoding method (for arrays), it didn't compile:
但是当我想尝试实现一种新的解码方法(对于数组)时,它没有编译:
std::tuple<std::array<uint16_t, 100>, std::array<uint8_t, 100>> data;
Here is the error (gcc-4.9). 这是错误(gcc-4.9)。
So I don't understand why I get this error. 所以我不明白为什么我会收到这个错误。 Because of the test
std::is_integral<X>::value
the data should not be evaluated in DecodeIntegral( x, buffer, index );
由于测试
std::is_integral<X>::value
,不应在DecodeIntegral( x, buffer, index );
right ? 对 ?
Please not the this is work in progress so there are certainly a few mistakes and improvements to make. 请注意,这不是正在进行的工作,因此肯定会有一些错误和改进。 And thank you for your help !
谢谢你的帮助!
I admit I haven't gone through all of the code, but I believe your issue is with runtime vs. compile-time conditions. 我承认我没有完成所有代码,但我相信你的问题是运行时与编译时条件。 You cannot use a run-time condition (like
if (std::is_integral<:::>::value>)
to prevent compile-time errors. 您不能使用运行时条件(如
if (std::is_integral<:::>::value>)
来防止编译时错误。
I understand DecodeIntegral
is only compilable when X
is indeed integral. 我知道当
X
确实是积分时, DecodeIntegral
只能编译。 Therefore, you must make sure a call to DecodeIntegral
with a non-integral X
is never seen by the compiler (ie instantiated), and not just that it never occurs at runtime. 因此,您必须确保编译器永远不会看到带有非整数
X
DecodeIntegral
调用(即实例化),而不仅仅是它永远不会在运行时发生。
Seeing as the function DecodeIntegral
could easily be a static member without any change in semantics, you can use the "delegate to class" trick to achieve this. 看作函数
DecodeIntegral
可以很容易地成为一个静态成员而没有任何语义变化,你可以使用“delegate to class”技巧来实现这一点。 Move DecodeIntegral
into a helper class: 将
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);
}
};
Added based on request in comment 根据评论请求添加
If you need more than one discriminator, add more bool
template parameters to the helper. 如果需要多个鉴别器,请向辅助对象添加更多
bool
模板参数。 If there is no standard predicate for a discriminator you need, you can write your own. 如果您需要的鉴别器没有标准谓词,您可以自己编写。
(The example below assumes the discriminators are exclusive - at most one is 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);
}
};
The std::is_integral<X>::value
evaluates to false
, but that does not mean that the code below ( DecodeIntegral( x, buffer, index );
) is "skipped". std::is_integral<X>::value
计算结果为false
,但这并不意味着下面的代码( DecodeIntegral( x, buffer, index );
)被“跳过”。 The compiler sees this line, too. 编译器也看到了这一行。 So, currently you have a runtime-condition, but you actually want a compile-time condition.
所以,目前你有一个运行时条件,但实际上你需要一个编译时条件。
Edit: I just wanted to edit my answer with a short example, but Angew was faster. 编辑:我只是想用一个简短的例子来编辑我的答案,但是Angew更快。 See his answer :)
看他的回答:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.