在C 中超载Bitshift操作员
Overloading bitshift operator in c++
我想对arm_neon.h
中的ARM系统定义的uint32x4_t
超载Bitshift运算符。
struct uint32x4_t {
uint32_t val[4];
};
这应该通过呼叫SIMD函数来完成,该功能期望值转移并立即发生恒定:
uint32x4_t simdShift(uint32x4_t, constant_immediate);
shift.h
#ifndef SHIFT_H
#define SHIFT_H
namespace A {
namespace B {
/*uint32x4_t simdLoad(uint32_t*) {
...
}*/
template<int N>
uint32x4_t shiftRight(uint32x4_t vec) {
return vshrq_n_u32(vec,N);
}
}
}
uint32x4_t operator>>(uint32x4_t const & vec, const int v) {
return A::B::shiftRight<v>(vec);
}
#endif
main.cpp
#include "shift.h"
int main() {
uint32_t* data = new uint32_t[4];
data[0] = 1;
data[1] = 2;
data[2] = 3;
data[3] = 4;
uint32x4_t reg;// = simdLoad(data);
reg = reg>>3;
return 0;
}
此代码产生错误:
‘uint32x4_t运算符>>(const uint32x4_t&amp;,int)必须有一个参数 类或枚举类型的Uint32x4_t运算符>>(UINT32X4_T const&amp; vec,const int v){
是否有解决"本机"类型(例如uint32x4_t
)的operator>>
的解决方法?
编辑:我调整了建议的解决方法,但错误仍然保持不变:(
ermig答案的增量改进:
template<int N>
constexpr std::integral_constant<int, N> i_{};
template<int N>
uint32x4_t operator >>(uint32x4_t value, std::integral_constant<int, N>) noexcept {
return _mm_slli_si128(value, N);
}
int main() {
std::uint32_t data[4] = {1, 2, 3, 4};
uint32x4_t reg;// = simdLoad(&data);
reg = reg >> i_<3>;
}
n.b。我将operator>>
放在全局名称空间中;如果您想将其放在其他名称空间中,则需要在使用之前将操作员带入范围。
" uint32x4_t是一种本地类型,由arm_neon.h提供。(来自另一个评论)。
您最初面临的问题是C 使用了所谓的参数依赖性查找。对于A::B::uint32x4
,C 将考虑A::B::operator>>(uint32x4, int)
。也就是说,C 将以各自参数的命名空间查看。
您的问题是uint32x4
位于全局名称空间中,但您将operator>>
放在另一个名称空间中。那完全是错的。将其放在正确的名称空间中。
请注意,名称空间是避免名称冲突的两种机制之一。超载是另一种机制。名称空间适用于所有类型的名称:变量,类型和功能。超载仅适用于功能。但是在这种情况下,这是足够的,因为操作员是功能的子集。您不会得到名字冲突;您的operator>>
超载与其他operator>>
。
用于使用恒定立即的函数调用(通常在SIMD Intrinsics中相遇),我通常将模板函数与整数模板参数一起使用。以下示例使用SSE2,但对于霓虹灯,它会相似:
template<int shift> __m128i Shift(__m128i value)
{
return _mm_slli_si128(value, shift);
}
int main()
{
__m128i a = _mm_set1_epi8(3);
__m128i b = Shift<2>(a);
return 0;
}
不幸的是,我不知道如何为C 操作员制作它。当然,我们可以使用模板参数创建一个操作员,但是使用以下方式非常不便:
template<int shift> __m128i operator >> (__m128i value, int shift_)
{
return _mm_slli_si128(value, shift);
}
int main()
{
__m128i a = _mm_set1_epi8(3);
__m128i b = operator >> <2>(a, 2);
return 0;
}
@ildjarn启发的变体:
template<int N> struct Imm {};
#define IMM(N) Imm<N>()
template<int shift> __m128i operator >> (__m128i value, Imm<shift>)
{
return _mm_slli_si128(value, shift);
}
int main()
{
__m128i a = _mm_set1_epi8(3);
__m128i b = a >> IMM(2);
return 0;
}
一种解决方案是将operator>>
从A::B
名称空间移动到全局名称空间。如果所有其他符号都是不同的命名空间,那么您只需要限定它们即可。例如,如果simdShift
在A::B
中,您仍然可以像这样具有全局operator>>
:
uint32x4_t operator>>(uint32x4_t const & vec, const int v) {
return A::B::simdShift(vec, v);
}
,但我想使operator>>
成为uint32x4_t
的成员更合适:
struct uint32x4_t {
uint32_t val[4];
uint32x4_t operator>>(const int v) const;
};
namespace A { namespace B {
/// TODO: Put declaration/definition of simdShift here
}} // namespace A { namespace B {
uint32x4_t uint32x4_t::operator>>(const int v) const {
return A::B::simdShift(*this, v);
}
或或者,正如Ildjarn在评论中所建议的那样,将A::B
名称空间中的符号拉到您通过写作使用的上下文中:
using namespace A::B;
- <<操作员在下面的行中工作
- C++ 与操作员不匹配<<
- 操作员C++的模棱两可的过载
- C++中>>操作员过载时出现问题?
- NaN 上的宇宙飞船操作员
- 比根<操作员
- SFINAE不能防止模棱两可的操作员过载吗?
- 什么是现实中的"endl"(或任何输出操纵器)?它是如何实现的,它如何与操作员<<一起工
- 为什么"delete"操作员给我访问权限冲突
- 为什么使操作员成为新的专用会打破 std::shared_ptr?
- 在这种情况下是私有的吗?试图使操作员<<过载
- C++操作员过载>>
- 是否有 C++20 浮点数的包装器,使我能够默认宇宙飞船操作员?
- 与异常处理程序中的操作员<<不匹配
- 复印作业操作员说明
- 友谊和操作员+=重载
- >操作员在比较两个C++容器时会怎么做?
- 与操作员比较两个计时时间点
- C++操作员订单评估
- 在C 中超载Bitshift操作员