2016-03-04 21 views
10

Per questo particolare progetto, non sono in grado di utilizzare le funzionalità di C++ 11 (ad esempio decltype) perché il compilatore non le supporta ancora. Ho bisogno di essere in grado di fornire la classe corrente come parametro di template, preferibilmente all'interno di una macro senza un argomento (vedi sotto), senza vestire la dichiarazione class o nascondere graffe, eccCome posso recuperare il tipo della classe base in C++?

class Foo: private Bar<Foo> { 
    MAGIC //expands to using Bar<Foo>::Baz; and some others 
    public: 
     void otherFunction(); 
     //... the rest of the class 
}; 

Idealmente, I Mi piacerebbe che funzionasse molto come la macro di Qt Q_OBJECT, ma senza introdurre un altro passo di pre-compilazione e classi generate associate. typeid potrebbe essere utile in fase di esecuzione, ma il mio obiettivo è quello di realizzare tutto questo al momento della compilazione.

Come si scrive la macro MAGIC in modo che non sia necessario ripetere il nome della classe ogni volta?

+0

Questa domanda sembra essere la versione C++ 03 di "[Posso implementare un tipo di membro autonomo' self' in C++?] (http://stackoverflow.com/q/21143835/ 560648) " –

+1

Mente se cambio il titolo in * base clase *? * racchiudere la classe * fa sembrare che tu stia nidificando e quale sia il tipo fuori dalla classe esterna. – NathanOliver

+0

La domanda 'self' sembra molto simile, ma non sembra che nessuna delle soluzioni proposte funzioni in C++ 03, come hai notato. Certamente cambia il titolo se lo renderà più chiaro. – multipleinterfaces

risposta

0

È possibile utilizzare un "proxy" struct per Costruire l'eredità (?):

template <typename S> 
struct Base : public S{ //always public, access is restricted by inheriting Base properly 
    using super = S; 
}; 

uso potrebbe essere il seguente:

#include <iostream> 

template <typename S> 
struct Base : public S { 
    using super = S; 
}; 

template <typename T> 
class Bar 
{ 
public: 
    virtual void f() { std::cout << "Bar" << std::endl; } 
}; 

class Foo : private Base<Bar<int>> 
{ 
public: 
    virtual void f() 
    { 
     std::cout << "Foo"; 
     super::f(); //Calls Bar<int>::f() 
    } 
}; 

class Fii : private Base<Foo> 
{ 
public: 
    virtual void f() 
    { 
     std::cout << "Fii"; 
     super::f(); //Calls Foo::f() 
    } 
}; 


int main() 
{ 
    Fii fii; 
    fii.f(); //Print "FiiFooBar" 
    return 0; 
} 
0

Non credo che ci sia qualsiasi lingua meccanismo supportato per estrarre il tipo base da una classe. È possibile utilizzare:

Opzione 1

class Foo: private Bar<Foo> { 

#define BASE_TYPE Bar<Foo> 
    // Use BASE_TYPE in MAGIC 
    MAGIC //expands to using Bar<Foo>::Baz; and some others 
#undef BASE_TYPE 

    public: 
     void otherFunction(); 
     //... the rest of the class 
}; 

Opzione 2

class Foo: private Bar<Foo> { 

    typedef Bar<Foo> BASE_TYPE; 

    // Use BASE_TYPE in MAGIC 
    MAGIC //expands to using Bar<Foo>::Baz; and some others 

    public: 
     void otherFunction(); 
     //... the rest of the class 
}; 
+1

È possibile evitare la ridondanza con '#define 'ing' BASE_TYPE' _before_ la dichiarazione della classe, in modo da poter dire 'classe Foo: private BASE_TYPE'. – mindriot

+3

Oppure mantienilo nella classe e usa 'typedef' invece di' # define' come 'typdef Bar BaseType;' –

+0

@RyanHaining, ecco perché ho il '# undef' subito dopo la riga' MAGIC'. –

1

Che dire:

template<typename T> 
class Base 
{ 
protected: 
    typedef Base<T> MagicBaseType; 
    namespace Baz { } 
}; 

class Derived1 : private Base<Derived1> 
{ 
    using MagicBaseType::Baz; 
} 


class Derived1 : private Base<Derived2> 
{ 
    using MagicBaseType::Baz; 
} 

o, se non è possibile modificare il Base definizione, utilizzando modelli e mu eredità ltiple

template<typename T> 
class Base 
{ 
protected: 
    namespace Baz { } 
}; 

template<typename T> 
class DerivedTemplate : public T 
{ 
protected: 
    typedef typename T BaseType; 
} 

class Derived : public Base<Derived>, public DerivedTemplate<Base<Derived>> 
{ 
using BaseType::Baz; 
} 
0

Se davvero non si preoccupano formattazione o la scrittura di un mal di testa di manutenzione si può fare questo senza ripetere il tipo da avere la macro prendere il tipo di argomento:

#define MAGIC(BASE) \ 
BASE { \ 
    using BASE::baz; 

class Sub : private MAGIC(Base<Foo>) 

    public: 
    void otherFunction(); 
}; 

ma questo fa mi sento piuttosto male per me stesso

Problemi correlati