有没有一种通用的方法可以从所有类属性中创建元组?

时间:2020-11-07 17:05:32

标签: c++

我有许多类使用std::tie从所有class属性中创建一个元组,并使用它来实现==运算符。他们看起来像这样:

class S
{
    int number;
    std::string text;
    // and many other attributes...
    
    auto tied() const noexcept { return std::tie(/* list all attributes here */); }
    
    bool operator==(const S &o) const noexcept
    {
        return tied() == o.tied();
    }
};

这些类具有相似的方法,但是属性却非常不同,因此我想创建一个它们都继承自的基类,并且希望在基类中包含这种比较。

但是,由于我无法定义返回virtual的{​​{1}}方法,因此我很难编写一个抽象的通用auto方法,该方法应在所有派生对象中构成一个元组类的属性,无论它们有多少个或属于哪种类型。

这可行吗?

注意:所有属性都是普通类型或tied() s。

2 个答案:

答案 0 :(得分:1)

是否有一种通用的方法可以从所有类属性中创建元组?

无法生成成员列表。这是一种语言功能,需要比C ++更多的反射功能。充其量,您可以有一个同时生成成员声明和用于生成元组的函数的宏。有关该想法的实现,请参见Boost Fusion。

当然,您不限于用于元编程的C预处理器。如果您不介意使构建过程复杂化,则可以使用任何语言生成C ++源代码。

我正在努力写一个抽象的通用tie()

无法编写虚拟成员函数,该函数将为派生实例返回不同的元组。

这可行吗?

否。

并使用它来实现==运算符。

从C ++ 20开始,您可以使用默认的<=>生成所有比较运算符。在此之前,您需要样板。

答案 1 :(得分:1)

如果元素数量有限,则可以使用CRTP和https://stackoverflow.com/a/39779537/1774667查找元素数量。

使用结构化绑定,您可以根据它们构建一个元组。

这可以写在CRTP库中。

template<class T>
struct implement_equals {
  friend bool operator!=(implement_equals const& lhs, implement_equals const& rhs ) {
    return !(lhs==rhs);
  }
  T const& self() const {
    return *static_cast<T const*>(this);
  }
  friend bool operator==(implement_equals const& lhs, implement_equals const& rhs) {
    constexpr std::size_t count = construct_airity<T>;
    return make_tie_from<count>{}(lhs.self()) == make_tie_from<count>{}(rhs.self());
  }
};

接下来写make_tuple_from

template<std::size_t>
struct make_tie_from;

template<>
struct make_tie_from<1> {
  template<class T>
  auto operator()( T const& t ) const {
    auto const&[e0] = t;
    return std::tie(e0);
  }
};

然后写下其中的20个。

已经有一些库可以为您完成此工作,您可以通过一些谷歌搜索找到它们。它们都不是完美的,并且都要求您要公开发布数据。

如果您想隐藏该数据,请创建一个公开包含数据的结构以获取联系,并为Implement_equals提供某种方式以访问该结构(朋友,无论如何)。


中,您甚至无法进行反射。

您可以写implement_equals,但必须手动写平局。但是,它比虚函数要好。