2015-05-06 40 views
7

Bool değerlerindeki bir vektörü temsil eden bir C veri yapısına sahibim; Kontrollerimin dışındaki nedenlerden dolayı, boole'lar, gerçek ve yanlışları temsil eden iki büyülü değerle (0 ve 1 değil) dahili olarak tamsayı olarak depolanırlar. Bu C yapısını sarmalayan bir C++ sınıfı oluşturdum ve güzel çalışıyor. Ben set() ve get() yöntemlerini uygulayan:C++ aşırı yük [] dönüşümlü

void Class::set(size_t index , bool value) { 
    if (value) 
     c_ptr[index] = SPECIAL_TRUE_VALUE; 
    else 
     c_ptr[index] = SPECIAL_FALSE_VALUE; 
} 

Bu Tamam çalışır; ama ideal olarak [] operatörüne aşırı yüklenmek isterim, ancak bunu nasıl yapabilirim ki/yapabilirim - bool ve tamsayı değerleri arasındaki özel dönüşümden dolayı? Class yılında

+1

* Proxy sınıfları hakkında biraz bilgi okumanız gerekiyor * – vsoftco

+0

Evet - Bugün vekil derslerini öğrendim - ve atama operatörünü aşırı yükledim; Genelde yapmakta biraz isteksiz oldum. – user422005

+0

Bu, çözümünüz için geçerli olabilir veya olmayabilir, ancak dönüşümlerin sıklığına karşı, boole erişimlerinin sıklığını düşünmelisiniz. Öncelikle set/get/[] işlevlerini kullanıyor ve nadiren SPECIAL _ * _ VALUE dönüşümünü kullanıyorsanız, yalnızca bobinleri depolamak ve gerektiğinde dönüştürmek daha kolay olabilir. – nic

cevap

7
struct pseudo_reference { 
    operator bool()const&&{ 
    return c->get(index); 
    } 
    pseudo_reference operator=(bool b)&&{ 
    c->set(index, b); 
    return {c,index}; 
    } 

    // sometimes having named functions is useful: 
    bool get() const&& { 
    return std::move(*this); 
    } 
    void set(bool b)&& { 
    std::move(*this) = b; 
    } 
    pseudo_reference()=delete; 
private: 
    Class* c; 
    size_t index; 
    pseudo_reference(pseudo_reference&&o)=default; // not exposed 
    pseudo_reference(Class* pc, size_t i):c(pc),index(i){} 
    friend class Class; 
}; 

:

pseudo_reference operator[](size_t i){ 
    return {this, i}; 
} 
bool operator[](size_t i)const{ 
    return c_ptr[index] == SPECIAL_TRUE_VALUE; 
} 

Ben bir işaretçi ve bir dizin hem saklanan, bu yüzden pseudo_reference içinde get/set mantığını reimplementing kaçınırız. Böyle pseudo_references muhtemelen kısa ömürlü olacak, bu yüzden boyut optimizasyonu muhtemelen önemli değil.

pseudo_reference depolamaktan vazgeçmek için tüm rutin olmayan işlemleri engelledim. Sözü edilen işlemlerin rnnnn nispeten zararsız bir şekilde kısıtlanmasını sağlayabilirsiniz, fakat benim tecrübemde pseudo_references referanslar gibi davranan değerlerdir, bu yüzden devam etmemek daha iyidir.

Birisi pseudo_reference'u auto&& x = c[33]; aracılığıyla saklayabilir, ancak move olmadan kullanmak mümkün olmayacaktır. Umarım bu, en hata eğilimli kullanır. auto x = c[33]; çalışmıyor.

+0

@ user1978011 tarafından yapılan bir düzenleme girişimine yanıt olarak: Özel amaçlı bu amaçla yaptım. 'Arkadaş sınıfı Sınıf', 'Sınıf'ın' psödo_referans'ı oluşturmasına izin vermelidir. – Yakk

+0

Tamam - Sanırım nasıl çalıştığını anladım? 'Set()' yöntemine her erişim için bir pseudo_reference başlatacaksınız? Bu biraz ağır gözüküyor mu? – user422005

+1

@ user422005 bir işaretçidir ('Class''a) ve' size_t'. Bu ağır ağırlık nasıl? Bir referans, bir işaretçi olarak tipik olarak uygulanır (varoluş dışında satır belirtilmemişse), bu nedenle verilere bir başvuru döndüren yalnızca birkaç bayttan bahsederiz. Tuzuna değen bir derleyici, varoluşunun dışına sıralayabilir, çünkü sadece 'set' veya işaretçiyi çağırmak için yeterince uzun yaşayabilir. "Get" veya "set" için ham çağrıya karşı optimizasyon ile profilleme yapın ve çok fazla fark varsa şok olurdum. Hemen çıkan küçük yığın nesneleri ** ucuz **. – Yakk

1

Sizin için ödevi işleyen bir sarmalayıcı yardımcı sınıfına dönebilirsiniz.

struct proxy { 
    proxy& operator=(bool value) { 
     c_.c_ptr[ index_ ] = value ? SPECIAL_TRUE_VALUE : SPECIAL_FALSE_VALUE; 
     return *this; 
    } 
    operator bool() const { // for when it's just used normally, not = 
     return c_ptr[ index ] == SPECIAL_TRUE_VALUE; 
    } 
private: 
    Class &c_; 
    size_t const index_; 
    proxy(Class &c, size_t index) : c_(c), index_(index) { } 
    friend class Class; 
} 

class Class { 
public: 
    proxy operator[](size_t index) { 
     return proxy(*this, index); 
    } 
    bool operator[](size_t index) const { // read-only access is easy 
     return c_ptr[ index ] == SPECIAL_TRUE_VALUE; 
    } 
    // ... 
}; 

Ya da böyle bir şey: o = sol tarafında göründüğünde operator[]() uygulamak için

struct WrapMe { 
    c_ptr_T &value; 
    WrapMe(c_ptr_T &_value) : value(_value) {} 
    // handles assignment of bool values 
    WrapMe & operator=(const bool b) { 
     value = (b) ? SPECIAL_TRUE_VALUE : SPECIAL_FALSE_VALUE; 
     return *this; 
    } 
    // handles cast to bool 
    operator bool() const { return value == SPECIAL_TRUE_VALUE; } 
}; 

class Class { 
    WrapMe operator[](const int idx) { return WrapMe(c_ptr[idx]); } 
    // ... 
}; 
2

, gerçek atama yapan bir vekil nesneyi döndürmek gerekir.

İlgili konular