2013-04-05 7 views
6

Mam kilka klas łańcuchowych, które można niejawnie przekonwertować na ciągi. Mam kilka zastosowań dla nich; Jednym z przykładów jest trzymać tekst, który musi być tłumaczone w czasie wykonywania przez gettext:Klasa podobna do łańcucha C++ z niejawną konwersją

class TranslatableString 
{ 
public: 
    explicit TranslatableString(const char *s) : native_text_(s) {} 
    operator const char *() const { return gettext(native_text_); } 

    // Or not - see below: 
    operator const std::string() const { return gettext(native_text_); } 

private: 
    const char * const native_text_; 
}; 

Teraz staram się zrobić za pomocą tej klasy jak najprostsze (czyli z użyciem powinno być tak samo jak struna dosłownym jak to możliwe). W szczególności chciałbym, aby oba następujące przykłady użycia działały:

const TranslatableString HELLO = TranslatableString("Hello, world!"); 

std::string ExampleA() { 
    return HELLO; 
} 

void ExampleB() { 
    std::string s; 
    s = HELLO; 
} 

Czy istnieje sposób, aby oba przykłady działały?

  • Gdybym to operator std::string, następnie ExampleB nie skompilować, mówiąc, że istnieje pewna dwuznaczność pomiędzy std::string::operator=(const char *) i std::string operator=(const std::string&) (co ma sens).
  • Jeśli nie dodaję operator std::string, to nie można skompilować przykładuA; pozornie niejawna konwersja TranslatableString na const char * na std :: string nie jest dozwolona, ​​chociaż nie rozumiem niejawnych zasad konwersji C++ na tyle dobrze, aby wyjaśnić dlaczego.

Odpowiedz

5

Tylko jedna zdefiniowana przez użytkownika konwersja jest dozwolona w każdej sekwencji konwersji, dlatego nie można przejść przez "const char*. (Zauważ, że const char* do std::string jest również konwersją zdefiniowaną przez użytkownika).

Czy potrzebujesz konwersji na const char*? Bez tego (i z okładką do std::string) oba przykłady działałyby.

Warto również rozważyć przechowywanie danych jako std::string wewnętrznie zamiast const char*. Nie musisz martwić się o problemy z alokacją, dane "znikają" pod twoimi rękami itp.

+0

Ma sens. Dzięki. (Ta klasa jest przeznaczona tylko do użycia z literałami łańcuchowymi, więc 'const char *' jest w porządku, gdzie indziej, prawie zawsze używam 'std :: string'.) –

1

Musisz zrezygnować z posiadania operator const char *. Zrób to jako explicit (C++ 11) lub podaj jako metodę c_str.

Konwersja TranslatableString na const char * na std::string jest niedozwolona, ​​ponieważ zawiera dwie konwersje zdefiniowane przez użytkownika.

Powiązane problemy