将 std::tie 与位字段一起使用似乎失败

Using std::tie with bit fields seems to fail

我在 C++17 中有以下代码,我在其中定义了一个 struct ,它是一个位掩码并且具有成员变量,这些成员变量是输入 bool.

我正在定义一个 tie 函数,以便我可以将它转换为可比较的 std::tuple 对象,这很方便。问题是:std::tie 似乎做错了什么,第一个成员变量的值似乎是 false 即使默认构造函数已将其正确初始化为 true.

手动获取 bool 对位字段的单个引用似乎按预期工作。

我目前正在使用 CLang 12。

这是代码:

#include <cassert>
#include <tuple>

struct Bitmask
{
    Bitmask( )
        : first{true}
        , second{false}
        , third{false}
    {
    }

    bool first : 1;
    bool second : 1;
    bool third : 1;
};

auto
tie( const Bitmask& self )
{
    return std::tie( self.first, self.second, self.third );
}

int main()
{
    Bitmask default_bitmask; 
    Bitmask custom_bitmask;
    custom_bitmask.first = false;
    custom_bitmask.second = true;

    const bool& ref_1 = default_bitmask.first;
    const bool& ref_2 = custom_bitmask.first;

    assert( ref_1 != ref_2 ); // this check works   

    assert( std::get< 0 >( tie( default_bitmask ) ) == true ); // this check fails
    assert( std::get< 0 >( tie( custom_bitmask ) ) == false ); // this check works
}

不可能有对位域的引用或指针。来自 cppreference :

Because bit fields do not necessarily begin at the beginning of a byte, address of a bit field cannot be taken. Pointers and non-const references to bit fields are not possible. When initializing a const reference from a bit field, a temporary is created (its type is the type of the bit field), copy initialized with the value of the bit field, and the reference is bound to that temporary.

来自 the standard :

The address-of operator & shall not be applied to a bit-field, so there are no pointers to bit-fields. A non-const reference shall not be bound to a bit-field (dcl.init.ref).

accompanying note :

[Note 3: If the initializer for a reference of type const T& is an lvalue that refers to a bit-field, the reference is bound to a temporary initialized to hold the value of the bit-field; the reference is not bound to the bit-field directly. See dcl.init.ref. — end note]

编译的唯一原因是 tieBitmask 类型作为 const。它的每个位域成员都被视为 const 并且 std::tie return 是一个 std::tuple 的 const 引用。正如上面引用的段落所说,这些引用指的是数据成员的副本,而不是那些实际的数据成员。然后,就像您尝试通过引用 return a const int & x = 10; 一样,您最终会得到一个悬空引用的元组。最后,尝试获取引用对象的值会导致未定义的行为。