2015-09-15 36 views
6

Çalıştığım yaygın bir tasarım problemi, iki değişkeni bir araya getirmem ve daha sonra anlamlı bir şekilde referans verme yeteneğini kaybetmem.std :: pair kullanabilir, ancak .first ve .second üye adlarını yeniden adlandırabilir miyim?

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? 

yerine temel yapılar yazma düşündünüz ettik ama sonra std::pair ile birlikte gelen pek çok yarar kaybetmek:

  • make_pair
  • üye olmayan aşırı operatörler
  • takas
  • edin
  • vb

first ve second veri üyeleri için bir alternatif tanımlayıcıyı yeniden adlandırmanın veya sağlamanın bir yolu var mı?

Ben std::pair kabul fonksiyonların hepsi kaldıraç umuyordum,
ama yine de aşağıdaki şekilde bunları kullanabilmek için: Bu çevrede alabilir

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

kullanabilirsiniz. Belki std :: pair sarar bir sınıf yapmak? –

+1

Muhtemelen görev tanımlandığı gibi aşırı yüklenen, ancak [BOOST_FUSION_DEFINE_STRUCT] (http://www.boost.org/doc/libs/1_59_0/libs/fusion/doc/html/fusion/adapted/define_struct.html) oluşturmanıza olanak tanır karşılaştırma operatörleri, takas vb. otomatik olarak oluşturulan, ancak özel alan adlarına/türlerine sahip bir yapı. – Mankarse

+1

Yapı kordları hakkında: std :: pair {int & x = this-> first; int & y = this-> ikinci; }; '? – Slava

cevap

7

bir yolu kullanmaktır std::tie. tie(), iyi isimlere sahip olmanız için adlandırdığınız değişkenlere dönüş yapabilirsiniz. Hiç tie() Ayrıca birlikte çalışacak bir tuple dönmek için işlevini değiştirirseniz

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 

bu bir başka avantajdır.

+0

Hurb Sutter yelkenlerini değişkenler olarak bildirmek güzel olurdu ama şu anda bir teklif bulamıyorum. Bunu buldum: https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/4yWRnzX7J7Y – NathanOliver

6

Sadece serbest fonksiyonları yapabilirsiniz:

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

Eric Niebler en tagged burada yardımcı olabilecek.

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

Ve benzer şekilde y_tag uygulamak (sadece y() üye işlev isimlerini değiştirmek) olabilir: temel fikri böyle alıcılar oluşturmaktır. Ardından:

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

Sonra

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

Ne yapabilirsiniz sanmıyorum

#define _px first 
#define _py second