2013-08-25 13 views
7

Powiązane pytanie: std::map default value for build-in type - Subtelna różnica polega na tym, że chcę więcej niż wiedzieć, czy wartość jest zainicjowana na 0, czy też nie, ale chcę określić "konstruktor". Nie dbam nawet o to, czy wiąże się to z obciążeniem z definicją klasy, po prostu chcę mieć czysty "specjalny" podstawowy typ. Mógłby to zrobić nawet syntaktyczny hack. Typ niebędny jest bardzo łatwy do wykonania, jest to całe zadanie konstruktora.Jak utworzyć podstawowy typ C++, który sam się inicjuje?

Chciałbym mieć hashmap unordered_map<void *, int>, ale aby wszystkie jego wartości domyślnie-zostały zainicjowane na -1 zamiast 0 lub śmieci. Wynika to z faktu, że zero jest poprawnym indeksem, a ja wolałbym domyślnie-zainicjować z pewnością nieprawidłową wartością.

myślę, widzę kilka niechlujstwa sposobów to może być wykonane z:

struct minus1 { 
    int i; 
    minus1() i(-1) {} 
}; 
unordered_map<void*, minus1> 

Ale nie podoba mi się to, bo muszę używać .i aby uzyskać dostęp do int, a tak naprawdę po prostu musi być int.

Dobrze więc może mam moja mapa obsłużyć to:

struct PointerToIDHash { 
    std::unordered_map<void *, int> h; 
    PointerToIDHash() { 
     // ctor is powerless to affect the initialized values of future insertions into h 
    } 
}; 

Dobrze, gówno teraz mam .h też. Uhhhh. Czy mogę odziedziczyć z szablonu? (brzmi to przerażająco, ale może to być czysty sposób, jeśli można go usunąć)

Jak utworzyć typ, który zachowuje się tak jak int, ale zawsze jest inicjowany na -1?

Wolałbym wiedzieć, jak to zrobić z C++ i bez niego.

+0

Myślałeś o zapewnienie operatora konwersji? – Zeta

+0

Co to jest? :) Powiedz mi więcej. –

+0

Spójrz na odpowiedź a.lasram. Zasadniczo o to mi chodziło. – Zeta

Odpowiedz

11
#include <unordered_map> 
#include <iostream> 

using namespace std; 

template<typename T, T default_value> 
class SelfInitializer 
{ 
public: 
    SelfInitializer(T x = default_value) : x(x) {} 
    operator T&() { return x; } 
    operator const T&() const { return x; } 
private: 
    T x; 
}; 

// demo 
int main() 
{ 
    using minus1 = SelfInitializer<int, -1>; 

    unordered_map<int, minus1> m; 

    m[7] = 3; // assignment works 

    minus1 x = 3; 

    int y = x; // conversion to int works 

    int z = int(x); // explicit conversion works 

    cout << m[7] << endl; 
} 
+0

+1 dla ogólnego rozwiązania. –

+0

Czy 'operator =' byłby przydatny? 'my_map [7] = 3' będzie wtedy działać. – Yakk

+0

@Yakk: Działa już ze względu na 'operator T &", zobacz demo. –

8

dodać operator konwersji int& tak, że zachowuje się jak struct minus1 int

struct minus1 { 
    int i; 
    minus1() : i(-1) {} 
    operator int&() { return i; } 
}; 
+2

Seksowna magia C++ tutaj. Lubię to. –

+2

Prawdopodobnie będziesz także potrzebował konstruktora konwertującego.'minus1 (int n): i (n) {}' [Lub w połączeniu z domyślnym konstruktorem, 'minus1 (int n = -1): i (n) {}'.] – aschepler

+0

@aschepler Yep, kompilator powiedział mi, że dużo :) –

Powiązane problemy