2011-12-30 14 views
6

Jeśli musiałbyś przepisać poniższy kod C++ w D, jak byś to zrobił?Jak przepisać kod C++, który używa zmiennego w D?

struct A{ 

    const S* _s; 
    B _b; 
    C _c; 
    mutable C _c1, _c2; 

    A(const B& b, const C& c, const S* s){ /*...*/ } 

    void compute(const R& r) const 
    { 
     //... 
     _c1 = ... 
     _c2 = ... 
    } 
}; 

D nie posiada mutable, i na podstawie mojego doświadczenia, to rzadko stosowane w C++. Ale zakładając, że mutable jest używany z właściwych powodów tutaj, jakie są moje opcje w D?

+0

Jest to podobne pytanie: http://stackoverflow.com/questions/4219600/logical-const-in-d –

Odpowiedz

3

Masz trzy opcje do czynienia z tym:

  1. Odrzuć const. Spowoduje to awarię kompilatora, ale nie ma gwarancji, że twój kod będzie działał zgodnie z zamierzeniami. W szczególności, jeśli wywołasz tę funkcję na tym samym obiekcie z wielu wątków, jesteś na łasce wyścigów danych.

  2. Użyj zewnętrznego strukturę danych do przechowywania zmienny obiekty:

    struct A 
    { 
        static C[const(A)*] _c1s, _c2s; 
    
        void compute(ref const(R) r) const 
        { 
         _c1s[&this] = ... 
         _c2s[&this] = ... 
        } 
    } 
    

    Używam &this jako klucz do zewnętrznego tabeli mieszania, ale prawdopodobnie będzie lepiej wyłączyć za pomocą jakiegoś unikalnego identyfikatora . To bardzo brzydkie i trudne rozwiązanie. Nie lubię tego. Należy również zauważyć, że tablice skrótów są lokalnymi wątkami, więc ten sam obiekt będzie miał różne wartości na różnych wątkach. Może to być pożądane lub nie dla twojej aplikacji.

  3. zastanowić się, jak użyć const w D.

    D, const jest przechodnia i bitowe tj logiczne const nie jest obsługiwane. Ma to na celu zabezpieczenie przed współbieżnymi współdzielonymi zapisami danych. Nawet jeśli twój kod może być logicznie const prawidłowy, to nadal będzie się zrywał, jeśli dwa wątki próbowały wywołać compute na tym samym obiekcie, więc D nie zezwala na to i nie zapewnia legalnej ucieczki (nr mutable).

    Zasadniczo należy oznaczać funkcje jako const tylko wtedy, gdy są bitowe const.

    Powoduje to, że powinieneś używać const dużo mniej w D niż w C++, ponieważ potrzebujesz const bitowej o wiele mniej niż potrzebujesz stałej logicznej.

    Jako przykład rozważmy prosty (bezsensowne) generic equal funkcyjny, który mówi, czy dwa obiekty są równe:

    bool equal(T)(T lhs, T rhs) { return lhs == rhs; } 
    

    Zauważ, że nie zostały oznaczone parametry funkcyjne jak const. Jest to celowe. Testowanie równości nie powinno wymagać stałej bitowej - wymaga tylko stałej logicznej, więc wymuszenie poziomu const na obiektach byłoby niepotrzebnie restrykcyjne.

    Jak jA_cOp mówi, społeczność D nie widzi miejsca dla logicznej stałej w D, na lepsze lub na gorsze. Problem pojawia się, gdy próbujesz użyć const D's jak const C++. Nie są one takie same, więc nie używaj ich w taki sam sposób! Jeśli istnieje jakakolwiek możliwość, że funkcja może wymagać użycia stałej logicznej, nie oznaczaj jej jako stałej bitowej!

+0

podobny do twojego 'równego()', zrobiłem większość moich parametrów funkcji 'const' i do tej pory nie miałem z tym żadnych problemów. Czy to dlatego, że 'const' jest nadal zepsuty? – Arlen

+0

Myślę, że const działa obecnie. Niektóre rzeczy w Phobos nie są jednak poprawne (myślę) i jest duży problem z konstruktorami po blit, ale myślę, że większość const działa. –

+0

Tak więc, zamiast mieć większą swobodę przy dodawaniu const (w C++), w D jest odwrotnie; bardziej restrykcyjne jest ustawianie parametrów? –

6

D's immutable się przechodnia, przy podawaniu niezmiennej odniesienia (na przykład odniesienie w niezmiennej funkcji składowej this), wszystkie pola są również niezmienne. Nie ma możliwości obejścia tego problemu w D. const istnieje tylko w D, aby powiązać zmienne i niezmienne dane, ale ponieważ niezmienna jest niejawnie możliwa do przekształcenia w const, musi być również przechodnią. Gdy przejdziesz do niezmiennego (lub stałego), nie możesz wrócić.

Korzyści są następujące: niezmienne dane mogą być bezpiecznie dzielone przez wątki, mogą być umieszczane w pamięci ROM, jeśli są pożądane i łatwo je zrozumieć.

Po prostu nie ma miejsca na logiczną const w D, na lepsze lub na gorsze.

+0

więc sugeruje, że zrobię '_c1',', '_c2' obliczeniową () 'i wszystkie odniesienia do' A' non const? – Arlen

+0

@Alen, to twój jedyny wybór, jeśli chcesz zmutować obiekt 'this' w swojej metodzie. Zauważ, że nadal możesz zmutować dane przechowywane gdzie indziej (duh), które możesz czasami wykorzystać, gdy intencją jest użycie zmiennych danych do celów pamięci podręcznej. Ale takie zewnętrzne buforowanie jest brzydkie w ogólnym przypadku (hash map itp. Do towarzyszącego cache? Ew!) I pozostaje nierozwiązanym problemem. –

4

Krótka wersja; nie możesz, według projektu.

Dłuższa wersja, twórcy D zawarli (po kilku epickich debatach), że korzyści z mutable są przewyższane przez wady. (Patrz: odpowiedź jA_cOp dla niektórych szczegółów, wiele innych reaons są napędzane przez intencji, aby programowanie współbieżne i nie mniej brzydki rozumowanie.)

Powiązane problemy