2016-01-27 23 views
17

Czy istnieje sposób zbudowania typedef wewnątrz deklaracji typu na zadeklarowanym (otaczającym) typie bez podawania nazwy typu?Typedef do otaczającego typu w C++

przykład:

class X 
{ 
    public: 
    typedef <fill in magic here> MyType; 
    //... 
}; 

Tło: Wydaje głupie na pierwszy rzut oka. Potrzebuję tego, ponieważ używam makr do kompilacji w czasie moich klas danych. Tak więc w deklaracji klasy danych znajduje się makro, które musi zajmować się typem, w którym jest wstawiane. Do tej pory znalazłem rozwiązania robocze dla MSVC i g ++, które polegają na tym, co uważam za wadę w implementacji. Mogą więc nie działać w nowszej wersji. Clang nie "je" ani jednego z tych rozwiązań.

Moje obecne rozwiązanie dla MSVC definiuje metodę, a następnie przyjmuje adres tylko według jej nazwy i wywołuje małego pomocnika, który "zwraca" typ swojej klasy. (Clang i g ++ oczekują pełnej nazwy metody, włącznie z jej nazwą klasy).

Moje obecne rozwiązanie dla g ++ definiuje metodę statyczną z typem powrotu std::remove_reference(decltype(*this)). (Clang i MSVC nie pozwalają na this w kontekście statycznym).

Bezwarunkowo wolałbym standardowe rozwiązanie, ale specjalne rozwiązanie dla klang również byłoby w tej chwili w porządku.

Jeśli nic nie działa, muszę podać nazwę klasy do makra, ale staram się tego uniknąć, ponieważ mam już dużo kodu przy użyciu makra.

EDIT: Dodanie próbki, w jaki sposób działa odbicie (który może wyjaśnić to, czego potrzebuję):

class X : public Y 
{ 
    public: 
    //.. constructor and such stuff... 

    int a; 
    double b; 
    std::string c; 

    CLASSHEAD(Y) 
     FIELD(a) 
     FIELD(b) 
     FIELD(c) 
    CLASSFOOT 
}; 

CLASSHEAD jest makro, które powinno określać typedef. Jest to makro VAR_ARGS, w którym argumenty otrzymują klasy bazowe. Jak już wspomniano: możliwe jest nadanie mu nazwy klasy jako jej pierwszego argumentu (co daje w rezultacie CLASSHEAD(X, Y)). Ale prawie nie można sobie wyobrazić, że nie ma rozwiązania do takiego „po prostu” zadanie jako typedef'ing otaczającą typ ...

+0

Właściwie to nie jest dla mnie jasne, dlaczego nie można po prostu zrobić 'typedef X MyType;', a następnie mieć makra używające 'MyType'? – BoBTFish

+0

Czy wszystkie klasy, które będą używać tego mechanizmu, będą dziedziczyć z tej samej bazy? (W takim przypadku mogę przywrócić moją odpowiedź CRTP). – BoBTFish

+1

Jedyny powód, dla którego mogę myśleć o potrzebie tego, to podpisy funkcji. W samej funkcji używałbyś 'typedef std :: remove_reference (decltype (* this)) :: type MyType;' jak wyżej. Można utworzyć szablony funkcji, a następnie 'static_assert (std :: is_same :: value);'. Nie ładnie, nie można wymyślić nic lepszego. – BoBTFish

Odpowiedz

-3

Nohting działa więc przy użyciu klasy Nazwa w makrze jest jedynym działającym rozwiązaniem

2

nie dokładnie spełniają swoją specyfikację, ale myślę, że jest całkiem blisko:

class X 
{ 
//Stuff... 

//Use Macros to add: 
struct MyType; 

//Use class closing macro to insert variable between class-ending brace and semicolon  


} TYPE_VAR; 
//Perhaps add random stuff to TYPE_VAR name to avoid collisions, like __FILE__ 
struct decltype(TYPE_VAR)::MyType 
{ 
    typedef decltype(TYPE_VAR) V; 
}; 

Następnie dostępu typu X Korzystanie

X::MyType::V 

na przykład uproszczony CLASSFOOT może wyglądać następująco:

#define CLASSFOOT /*Your classfoot here*/ } TYPE_VAR; struct decltype(TYPE_VAR)::MyType {typedef decltype(TYPE_VAR) V; 
//No }; at end on purpose- this will come from the class in which you placed CLASSFOOT 

Czy jest to wystarczająco dobre dla twoich celów?

+0

Wadą jest to, że 'MyType :: V' nie może być użyte w definicji' X' (funkcja, o której myślę, że PO potrzebuje) –

+1

To nie odpowiada na pierwotne pytanie. – mmmmmmmm

0

Skoro już używasz makra, można korzystać z tego rozwiązania https://stackoverflow.com/a/21143997/2173029

#define CLASS_WITH_MY_TYPE(ClassName) \ 
    class ClassName     \ 
    {         \ 
     using MyType = ClassName; 

a następnie użyć jak

CLASS_WITH_MY_TYPE(X) 
public: 
    struct Y 
    { 
    using T = MyType; 
    }; 
}; 

static_assert(std::is_same<X, typename X::Y::T>::value, ""); 

oznaczone jako Wiki od @Chris wspomniano link i oryginalny odpowiedź była opublikowane przez @Bartek Banachewicz

+0

@ RüdigerStevens Myślałem, że chodzi ci o makro "CLASSHEAD". – Rumburak