c++ - 如何对(任意)POD C++ 结构施加词典顺序?

标签 c++ reflection lexicographic lexicographic-ordering

我有一些 POD struct foo;假设它是 struct foo { int x;无符号 y; }。我希望能够比较 struct foo 的使用字典顺序——当然是按照它们的字段顺序。也就是说,我希望所有运算符 <、==、> 等都适用于 struct foo

我可以用一些通用的方式来做到这一点,而不用任何 reflection voodoo 修饰我的结构定义吗? - 并且不只是拼出所有这些运算符定义?还是能够做到这一点“依赖于语言反射”的期望太高了?

最佳答案

您可以在 C++1z 中执行此操作。基于 this 的回答,我准备了以下概念证明:

struct anything {
    template<class T> operator T()const;
};

namespace details {
template<class T, class Is, class=void>
struct can_construct_with_N:std::false_type {};

template<class T, std::size_t...Is>
struct can_construct_with_N<T, std::index_sequence<Is...>,
        std::void_t< decltype(T{(void(Is),anything{})...}) >>:
                                                             std::true_type
{};
}

template<class T, std::size_t N>
using can_construct_with_N=details::can_construct_with_N<T, std::make_index_sequence<N>>;

namespace details {
template<std::size_t Min, std::size_t Range, template<std::size_t N>class target>
struct maximize: std::conditional_t<
    maximize<Min, Range/2, target>{} == (Min+Range/2)-1,
    maximize<Min+Range/2, (Range+1)/2, target>,
    maximize<Min, Range/2, target>
>{};

template<std::size_t Min, template<std::size_t N>class target>
struct maximize<Min, 1, target>: std::conditional_t<
    target<Min>{},
    std::integral_constant<std::size_t,Min>,
    std::integral_constant<std::size_t,Min-1>
>{};

template<std::size_t Min, template<std::size_t N>class target>
struct maximize<Min, 0, target>:
    std::integral_constant<std::size_t,Min-1>
{};

template<class T>
struct construct_searcher {
    template<std::size_t N>
    using result = ::can_construct_with_N<T, N>;
};

template<class T, std::size_t Cap=4>
using construct_arity = details::maximize< 0, Cap, details::construct_searcher<T>::template result >;

template<typename T>
constexpr auto tie_as_tuple_impl(std::integral_constant<size_t, 1>, T&& t){
    auto&& [a] = t;
    return std::tie(a);
}

template<typename T>
constexpr auto tie_as_tuple_impl(std::integral_constant<size_t, 2>, T&& t){
    auto&& [a,b] = t;
    return std::tie(a,b);
}

template<typename T>
constexpr auto tie_as_tuple_impl(std::integral_constant<size_t, 3>, T&& t){
    auto&& [a,b,c] = t;
    return std::tie(a,b,c);
}

template<size_t S, typename T>
constexpr auto tie_as_tuple(T&& t){
    return tie_as_tuple_impl(std::integral_constant<size_t, S>{}, std::forward<T>(t));
}

}

template<typename T>
constexpr auto tie_as_tuple(T&& t){
    constexpr size_t S = details::construct_arity<std::decay_t<T>>::value;
    return details::tie_as_tuple<S>(std::forward<T>(t));
}

现在,您可以使用 tie_as_tuple 创建一个元组,其中已按照您要求的方式定义了您要求的所有运算符。

demo

请注意,我必须准备多个 tie_as_tuple_impl 重载,每个重载对应一个结构中的每个元素数量,但它会随着结构元素的数量线性增长。


在 C++14 中有 magic_get 可以提供类似的解决方案,但它有其注意事项,请参阅 here 了解更多信息。

关于c++ - 如何对(任意)POD C++ 结构施加词典顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40564769/

相关文章:

C++ 格式化输入必须匹配值

c++ - 我无法将字符串存储到数组中,然后我想将其用于比较

java - 在 Java 中查找数组的维数

reflection - 在运行时确定 Kotlin 的版本

java.lang.NoClassDefFoundError : org/omg/CORBA/InterfaceDef 错误

mysql - SQL ROW 子查询中比较的顺序定义?

c++ - 有效地从 n-ary 树中删除节点列表

perl - 按字典顺序排序

c - 查找整数分区的字典顺序

C++ 复制构造函数中的命名空间冲突