根据唯一类型 id 比较两个 uint64_t 之间的多个位总是 returns true
Comparing multiple bits between two uint64_t's based on unique type id always returns true
我有一张地图,其中键是实体 ID (uint32_t
),值是“签名”,又名 uint64_t
,其中某些位集代表一种类型:std::unordered_map<uint32_t, uint64_t> m_entityComponents{};
我的目标是编写一个模板函数,它接受可变数量的类型并且 returns 无论实体中是否存在所有这些类型。我们称该函数为 bool hasAllComponents(uint32_t entity)
.
为此,我编写了一个方法,其中 returns 每个类型的唯一 ID:
template <class T>
uint8_t getTypeId()
{
static uint8_t s_type = ++m_nextComponentType;
return s_type;
}
然后,给定任意数量的类型,我通过使用折叠表达式调用 getTypeId()
来构造一个新的“签名”,将存在的每种类型的每个位设置为 1:
template<typename... Types>
uint64_t getTypesSignature()
{
return ((1 << getTypeId<Types>()) | ... | 0);
}
鉴于这两个辅助函数,我应该能够使用我的 hasAllComponents
方法检查地图中的实体是否具有所有传入的类型,该方法使用按位 &
运算符来将地图中缓存的签名与新创建的签名进行比较:
template<typename... Types>
bool hasAllComponents(uint32_t entity)
{
uint64_t signature = getTypesSignature<Types...>();
return (m_entityComponents[entity] & signature);
}
然而,hasAllComponents
仍然 returns 当只有部分位匹配时为真,而不是全部。我认为问题可能出在我的 getTypesSignature
折叠逻辑没有正确设置所有位,尽管打印出结果对我来说看起来不错。我的逻辑某处存在缺陷,如能帮助追踪,我将不胜感激!
您正在生成一个 signature
,其中包含设置为 1 的所有 必需的 位,但您没有正确检查实体的值是否确实具有 [=40=这些相同位的 ]all 设置为 1。您正在检查该值是否将这些相同位的 any 设置为 1。
本次比较:
return (m_entityComponents[entity] & signature);
&
运算符的结果将是 uint64_t
,可隐式转换为 bool
,因此 return
值将是 true
如果结果 uint64_t
是 non-zero,否则它将是 false
.
所以,假设计算出的 signature
是 107
(b01101011
)。这意味着值与这些位集的 any 的任何组合将导致 true
,例如:
1: b00000001 & b01101011 = b00000001, != 0? true
2: b00000010 & b01101011 = b00000010, != 0? true
4: b00000100 & b01101011 = b00000000, != 0? false
8: b00001000 & b01101011 = b00001000, != 0? true
16: b00010000 & b01101011 = b00000000, != 0? false
32: b00100000 & b01101011 = b00100000, != 0? true
64: b01000000 & b01101011 = b01000000, != 0? true
107: b01101011 & b01101011 = b01101011, != 0? true
128: b10000000 & b01101011 = b00000000, != 0? false
255: b11111111 & b01101011 = b01101011, != 0? true
为确保该值已设置 所有 所需位,您只需将比较更改为:
return ((m_entityComponents[entity] & signature) == signature);
仅当该值至少具有 signature
位集的 all 时(它可以有更多),结果才会是 true
,例如:
1: b00000001 & b01101011 = b00000001, == b01101011? false
2: b00000010 & b01101011 = b00000010, == b01101011? false
4: b00000100 & b01101011 = b00000000, == b01101011? false
8: b00001000 & b01101011 = b00001000, == b01101011? false
16: b00010000 & b01101011 = b00000000, == b01101011? false
32: b00100000 & b01101011 = b00100000, == b01101011? false
64: b01000000 & b01101011 = b01000000, == b01101011? false
107: b01101011 & b01101011 = b01101011, == b01101011? true
128: b10000000 & b01101011 = b00000000, == b01101011? false
255: b11111111 & b01101011 = b01101011, == b01101011? true
我有一张地图,其中键是实体 ID (uint32_t
),值是“签名”,又名 uint64_t
,其中某些位集代表一种类型:std::unordered_map<uint32_t, uint64_t> m_entityComponents{};
我的目标是编写一个模板函数,它接受可变数量的类型并且 returns 无论实体中是否存在所有这些类型。我们称该函数为 bool hasAllComponents(uint32_t entity)
.
为此,我编写了一个方法,其中 returns 每个类型的唯一 ID:
template <class T>
uint8_t getTypeId()
{
static uint8_t s_type = ++m_nextComponentType;
return s_type;
}
然后,给定任意数量的类型,我通过使用折叠表达式调用 getTypeId()
来构造一个新的“签名”,将存在的每种类型的每个位设置为 1:
template<typename... Types>
uint64_t getTypesSignature()
{
return ((1 << getTypeId<Types>()) | ... | 0);
}
鉴于这两个辅助函数,我应该能够使用我的 hasAllComponents
方法检查地图中的实体是否具有所有传入的类型,该方法使用按位 &
运算符来将地图中缓存的签名与新创建的签名进行比较:
template<typename... Types>
bool hasAllComponents(uint32_t entity)
{
uint64_t signature = getTypesSignature<Types...>();
return (m_entityComponents[entity] & signature);
}
然而,hasAllComponents
仍然 returns 当只有部分位匹配时为真,而不是全部。我认为问题可能出在我的 getTypesSignature
折叠逻辑没有正确设置所有位,尽管打印出结果对我来说看起来不错。我的逻辑某处存在缺陷,如能帮助追踪,我将不胜感激!
您正在生成一个 signature
,其中包含设置为 1 的所有 必需的 位,但您没有正确检查实体的值是否确实具有 [=40=这些相同位的 ]all 设置为 1。您正在检查该值是否将这些相同位的 any 设置为 1。
本次比较:
return (m_entityComponents[entity] & signature);
&
运算符的结果将是 uint64_t
,可隐式转换为 bool
,因此 return
值将是 true
如果结果 uint64_t
是 non-zero,否则它将是 false
.
所以,假设计算出的 signature
是 107
(b01101011
)。这意味着值与这些位集的 any 的任何组合将导致 true
,例如:
1: b00000001 & b01101011 = b00000001, != 0? true
2: b00000010 & b01101011 = b00000010, != 0? true
4: b00000100 & b01101011 = b00000000, != 0? false
8: b00001000 & b01101011 = b00001000, != 0? true
16: b00010000 & b01101011 = b00000000, != 0? false
32: b00100000 & b01101011 = b00100000, != 0? true
64: b01000000 & b01101011 = b01000000, != 0? true
107: b01101011 & b01101011 = b01101011, != 0? true
128: b10000000 & b01101011 = b00000000, != 0? false
255: b11111111 & b01101011 = b01101011, != 0? true
为确保该值已设置 所有 所需位,您只需将比较更改为:
return ((m_entityComponents[entity] & signature) == signature);
仅当该值至少具有 signature
位集的 all 时(它可以有更多),结果才会是 true
,例如:
1: b00000001 & b01101011 = b00000001, == b01101011? false
2: b00000010 & b01101011 = b00000010, == b01101011? false
4: b00000100 & b01101011 = b00000000, == b01101011? false
8: b00001000 & b01101011 = b00001000, == b01101011? false
16: b00010000 & b01101011 = b00000000, == b01101011? false
32: b00100000 & b01101011 = b00100000, == b01101011? false
64: b01000000 & b01101011 = b01000000, == b01101011? false
107: b01101011 & b01101011 = b01101011, == b01101011? true
128: b10000000 & b01101011 = b00000000, == b01101011? false
255: b11111111 & b01101011 = b01101011, == b01101011? true