2015-09-15 4 views
6

共通の設計上の問題は、2つの変数をまとめて意味のある方法で参照することができなくなることです。std :: pairを使用できますが、.firstと.secondのメンバー名を変更できますか?

私が代わりに基本的な構造体を書い考えられてきましたが、その後、私は std::pairと一緒に来るの利益の多くを失う
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? 

  • make_pair
  • 非会員オーバーロードされた演算子
  • スワップ
  • get
  • など

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); 
+0

を使用することができます。たぶん、std :: pair をラップするクラスを作るでしょうか? –

+1

おそらく、定義されているタスクのためにおそらく過剰ですが、[BOOST_FUSION_DEFINE_STRUCT](http://www.boost.org/doc/libs/1_59_0/libs/fusion/doc/html/fusion/adapted/define_struct.html)では、比較演算子、スワップなどが自動的に生成される構造体ですが、カスタムフィールド名/型があります。 – Mankarse

+1

'構造体コードについて:std :: pair {int&x = this-> first; int&y = this-> second; }; '? – Slava

答えて

7

一つの方法は、使用することですstd::tietie()名前を付けた変数への戻り値を返すことができます。あなたは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 

これでもう一つの利点はあります。

+0

Hurb Sutterセールでは、変数をネクタイで宣言できればうれしいですが、私は今すぐ提案を見つけることができません。私は見つけました:https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/4yWRnzX7J7Y – NathanOliver

6

あなただけの自由な機能を行うことができます。

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; } 
2

エリックNieblerのtaggedはここに役立つかもしれません。

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)); 
     } 
    }; 
}; 

そして、あなたは同様に(ちょうどy()にメンバ関数名を変更)y_tagを実装することができます。基本的な考え方は、あなたがこのようなゲッターを作成することです。その後:次に

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> 
    {}; 
} 

using coord_t = tagged<std::pair<int, int>, x_tag, y_tag>; 
0

あなたは私はあなたができるとは思わない

#define _px first 
#define _py second 
関連する問題