【问题标题】:Data member pointers as associative container keys数据成员指针作为关联容器键
【发布时间】:2022-01-06 15:55:47
【问题描述】:

我正在尝试创建 std::setpointers to data members。但是,我找不到对此类指针进行排序或散列的方法。

它们无法与operator< 进行比较,它们似乎不受std::less 的支持,并且没有标准的整数类型可以保证保持它们的表示形式(它们可能不适合std::uintptr_t) .

这是我首先尝试的 (https://godbolt.org/z/K8ajn3rM8):

#include <set>

struct foo
{
    int x;
    int y;
};

using t_member_ptr = int (foo::*);

const std::set<t_member_ptr> members = {
    &foo::x,
    &foo::y
};

它会产生错误error: invalid operands of types 'int foo::* const' and 'int foo::* const' to binary 'operator&lt;'。完整的错误消息还暗示这发生在 std::less 的实例化期间。

我发现了一个类似的问题 (Set of pointer to member),但它可以追溯到 C++14,答案归结为“将指针放入向量中并改为执行线性搜索”。

C++17 或 C++20 是否有任何更改使得可以使用指向数据成员的指针作为标准关联容器的键?

【问题讨论】:

    标签: c++ c++17 c++20 c++-standard-library data-member-pointers


    【解决方案1】:

    按字节比较它们,例如使用这个比较器:

    #include <cstring>
    #include <type_traits>
    
    struct BitLess
    {
        template <typename T>
        requires std::has_unique_object_representations_v<T>
        constexpr bool operator()(const T &a, const T &b) const
        {
            return std::memcmp(reinterpret_cast<const char *>(&a), reinterpret_cast<const char *>(&b), sizeof(T)) < 0;
        }
    };
    

    检查std::has_unique_object_representations_v&lt;T&gt; 确保内部没有填充。它在 GCC、Clang 和 MSVC 上进行了尝试,并且对所有三个上的成员指针都返回了 true。

    【讨论】:

    • 它还有助于确保没有可能重叠的子对象(参见eel.is/c++draft/intro.object#7)。没有(可能是零大小的)基类,没有属性为no_­unique_­address 的成员变量。也许最好使用标准布局类 (eel.is/c++draft/class.prop#3)。那么它应该绝对可以在编译器和编译器版本之间移植。
    • @Sebastian 如果has_unique_object_representations_v 返回true,我不明白为什么这些都可能成为问题。
    • 我提到的步骤有助于确保对象表示是唯一的。 has_unique_object_representations_v 仅在编译时有效(与代码的设计时相比),并且可能因代码更改或新的编译器版本而中断。更好地理解,当它确实有效或保证有效时。
    • @Sebastian Tbh,如果它返回 false,即使我没有执行您列出的任何操作,我也可能不相信编译器会将填充保持为零。我会尝试找出填充的确切位置,并在比较时忽略它。
    • 当然,绝不应该替代has_unique_object_representation_v,而是设计阶段的考虑。我说的是“帮助步骤”,而不是替代方案。如果它返回false(并且它应该绝对被静态检查),那应该是不行的。然后使用了不合适的类。
    猜你喜欢
    • 1970-01-01
    • 2014-06-29
    • 2012-03-22
    • 1970-01-01
    • 2014-11-08
    • 2013-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多