Tre*_*key 15 c++ typedef std-pair c++17
我遇到的一个常见设计问题是,我将两个变量捆绑在一起,然后失去了以有意义的方式引用它们的能力.
std::pair<int,int> cords;
cord.first = 0; //is .first the x or y coordinate?
cord.second = 0; //is .second the x or y coordinate?
Run Code Online (Sandbox Code Playgroud)
我考虑过编写基本结构,但后来失去了许多带来的好处std::pair:
有一种方法来重命名或用于提供一个替代标识符first和second数据成员?
我希望利用所有接受的功能std::pair,
但仍然可以通过以下方式使用它们:
std::pair<int,int> cords;
//special magic to get an alternative name of access for each data member.
//.first and .second each have an alternative name.
cords.x = 1;
assert(cords.x == cords.first);
Run Code Online (Sandbox Code Playgroud)
Nat*_*ica 12
你可以解决这个问题的一种方法是使用std::tie.您可以tie()返回已命名的变量,以便获得良好的名称.
int x_pos, y_pos;
std::tie(x_pos, y_pos) = function_that_returns_pair_of_cords();
// now we can use x_pos and y_pos instead of pair_name.first and pair_name.second
Run Code Online (Sandbox Code Playgroud)
这样做的另一个好处是,如果你改变函数以返回一个元组tie()也将使用它.
使用C++ 17,我们现在具有结构化绑定,允许您将多个变量声明并绑定到函数的返回.这适用于数组,元组/对象对象和结构/类(只要它们满足一些要求).在这种情况下使用结构化绑定允许使用将上面的示例转换为
auto [x_pos, y_pos] = function_that_returns_pair_of_cords();
Run Code Online (Sandbox Code Playgroud)
你也可以
auto& [x_pos, y_pos] = cords;
Run Code Online (Sandbox Code Playgroud)
现在x_pos是一个参考cords.first和y_pos参考cords.second.
你可以做免费的功能:
int& get_x(std::pair<int, int>& p) { return p.first; }
int& get_y(std::pair<int, int>& p) { return p.second; }
int const& get_x(std::pair<int, int> const& p) { return p.first; }
int const& get_y(std::pair<int, int> const& p) { return p.second; }
Run Code Online (Sandbox Code Playgroud)
埃里克·尼伯勒(Eric Niebler)的tagged帮助可能在这里。基本思想是,您可以这样创建getter:
struct x_tag {
template<class Derived, class Type, std::size_t N>
struct getter {
Type& x() & {
return std::get<N>(static_cast<Derived&>(*this));
}
Type&& x() && {
return std::get<N>(static_cast<Derived&&>(*this));
}
const Type& x() const & {
return std::get<N>(static_cast<const Derived&>(*this));
}
const Type&& x() const && {
return std::get<N>(static_cast<const Derived&&>(*this));
}
};
};
Run Code Online (Sandbox Code Playgroud)
您可以类似地实现y_tag(只需将成员函数名称更改为y())。然后:
template<class, class, class...> struct collect;
template<class Derived, std::size_t... Ns, class... Tags>
struct collect<Derived, std::index_sequence<Ns...>, Tags...>
: Tags::template getter<Derived, std::tuple_element_t<Ns, Derived>, Ns>...{};
template<class Base, class... Tags>
struct tagged : Base, collect<tagged<Base, Tags...>,
std::index_sequence_for<Tags...>, Tags...> {
using Base::Base;
// extra polish for swap and converting from other tagged's.
};
namespace std
{
template<typename Base, typename...Tags>
struct tuple_size<tagged<Base, Tags...>>
: tuple_size<Base>
{};
template<size_t N, typename Base, typename...Tags>
struct tuple_element<N, tagged<Base, Tags...>>
: tuple_element<N, Base>
{};
}
Run Code Online (Sandbox Code Playgroud)
然后
using coord_t = tagged<std::pair<int, int>, x_tag, y_tag>;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3998 次 |
| 最近记录: |