2015-09-15 5 views
6

Un problema di progettazione comune in cui mi imbatto è che raggruppo insieme due variabili e quindi non riesco a fare riferimento a esse in modo significativo.Posso usare std :: pair, ma rinominare i nomi dei membri .first e .second?

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? 

ho pensato di scrivere le strutture di base, invece, ma poi ho perso un sacco di benefici che vengono con std::pair:

  • make_pair
  • operatori non membro sovraccarichi
  • di swap
  • get
  • ecc.

C'è un modo per rinominare o fornire un identificativo alternativo per i membri di dati first e second?

speravo di sfruttare tutte le funzioni che accettano std::pair,
ma comunque in grado di usarli nel modo seguente:

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

Non credo che si può. Magari fai un corso che avvolge std :: pair ? –

+1

Probabilmente eccessivo per l'attività come definito, ma [BOOST_FUSION_DEFINE_STRUCT] (http://www.boost.org/doc/libs/1_59_0/libs/fusion/doc/html/fusion/adapted/define_struct.html) consente di generare una struttura che ha operatori di confronto, scambio, ecc generati automaticamente, ma con nomi/tipi di campi personalizzati. – Mankarse

+1

E riguardo 'struct cord: std :: pair {int & x = this-> first; int & y = this-> second; }; '? – Slava

risposta

7

Un modo si potrebbe ottenere intorno a questo è quello di utilizzare std::tie. Puoi tie() il ritorno in variabili che hai nominato in modo da avere un buon nome.

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 

Un altro vantaggio di questo è se mai cambiare la funzione per restituire una tupla tie() funziona anche con quella.

+0

Hurb Sutter salpare sarebbe bello poter dichiarare le variabili in pareggio ma non riesco a trovare una proposta in questo momento. Ho trovato: https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/4yWRnzX7J7Y – NathanOliver

6

Si può solo rendere le funzioni libere:

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 di tagged potrebbe aiutare qui. L'idea di base è che si crea getter come questo:

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

E si può allo stesso modo implementare y_tag (basta cambiare i nomi delle funzioni membro per y()). Poi:

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

Poi

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

È possibile utilizzare

#define _px first 
#define _py second 
Problemi correlati