一般来说,tuple 应该用在泛型代码中。
如果您知道字段 1 是数字或鸡,则不应使用 tuple。您应该使用带有名为 Number 的字段的 struct。
如果你需要类似元组的功能(就像你一样),你可以简单地写as_tie:
struct SomeType {
int Number;
std::string Chicken;
auto as_tie() { return std::tie(Number, Chicken); }
auto as_tie() const { return std::tie(Number, Chicken); }
};
现在您可以通过输入someInstance.as_tie() 来访问SomeType 作为引用的tuple。
这仍然不会免费为您提供< 或== 等。我们可以在一个地方执行此操作,并在您使用 as_tie 技术的任何地方重复使用它:
struct as_tie_ordering {
template<class T>
using enable = std::enable_if_t< std::is_base_of<as_tie_ordering, std::decay_t<T>>, int>;
template<class T, enable<T> =0>
friend bool operator==(T const& lhs, T const& rhs) {
return lhs.as_tie() == rhs.as_tie();
}
template<class T, enable<T> =0>
friend bool operator!=(T const& lhs, T const& rhs) {
return lhs.as_tie() != rhs.as_tie();
}
template<class T, enable<T> =0>
friend bool operator<(T const& lhs, T const& rhs) {
return lhs.as_tie() < rhs.as_tie();
}
template<class T, enable<T> =0>
friend bool operator<=(T const& lhs, T const& rhs) {
return lhs.as_tie() <= rhs.as_tie();
}
template<class T, enable<T> =0>
friend bool operator>=(T const& lhs, T const& rhs) {
return lhs.as_tie() >= rhs.as_tie();
}
template<class T, enable<T> =0>
friend bool operator>(T const& lhs, T const& rhs) {
return lhs.as_tie() > rhs.as_tie();
}
};
这给了我们:
struct SomeType:as_tie_ordering {
int Number;
std::string Chicken;
auto as_tie() { return std::tie(Number, Chicken); }
auto as_tie() const { return std::tie(Number, Chicken); }
};
现在
SomeTime a,b;
bool same = (a==b);
有效。注意as_tie_ordering 不使用CRTP,是一个空的无状态类;该技术使用Koenig lookup 让实例找到运算符。
您还可以实现基于 ADL 的get
struct as_tie_get {
template<class T>
using enable = std::enable_if_t< std::is_base_of<as_tie_get, std::decay_t<T>>, int>;
template<std::size_t I, class T,
enable<T> =0
>
friend decltype(auto) get( T&& t ) {
using std::get;
return get<I>( std::forward<T>(t).as_tie() );
}
};
让std::tuple_size 工作并不容易,很遗憾。
上面的 enable<T> =0 子句在 MSVC 中应替换为 class=enable<T>,因为它们的编译器不符合 C++11。
你会注意到上面我使用tuple;但我使用它一般。我将我的类型转换为一个元组,然后使用元组的< 来写我的<。该胶水代码将 tie 作为通用类型包处理。这就是tuple 的用途。