我有许多类使用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。
答案 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提供某种方式以访问该结构(朋友,无论如何)。
在c++14中,您甚至无法进行反射。
您可以写implement_equals
,但必须手动写平局。但是,它比虚函数要好。