bei typedefs trotz gleicher Basis Compilerfehler erzwingen



  • Kennt jemand eine Möglichkeit mit der man bei typedefs, die letztlich auf denselben Typ verweisen einen Fehler bekommt, wenn der Typ nicht dem "speziellen typedef" entspricht.

    Ein Beispiel sagt mehr als 1000 Worte:

    typedef A A1;
    typedef A A2;
    
    void foo( A1 ) {}
    
    int main() {
     A2 a2;
     foo( a2 ); //--> hier soll der Compiler einen Fehler melden
    }
    

    Ich dachte zuerst an BOOST_STRONG_TYPEDEF, der aber nur ambigous calls korrekt auflöst:

    BOOST_STRONG_TYPEDEF( A, A1 );
    BOOST_STRONG_TYPEDEF( A, A2 );
    
    void foo( A1 ) {}
    void foo( A2 ) {}
    
    int main() {
     A1 a1;
     foo( a1 ); //--> foo( A1 )
     A2 a2;
     foo( a2 ); //--> foo( A2 )
    }
    

    Allerdings erhält man keinen Compilerfehler, wenn im obigen Beispiel foo für A2 nicht definiert ist, da dann automatisch foo( A1 ) verwendet werden kann. Was im Normalfall ja auch genau so sein soll.

    In dem speziellen Fall möchte ich aber gerne genau dieses Verhalten vermeiden. Mir war so, als hätte irgendwo in boost ein Makro gesehen, dass sowas behandelt.



  • Interessante Frage. Da ein typedef ja nur ein Alias und kein neuer Typ ist, fällt mir nicht ein, wie man das lösen könnte, außer halt so, dass man einen eigenen Typ draus macht, was aber vermutlich nicht das ist, was willst, weil das dann nicht mehr mit Basistypen geht.

    struct A1 : A {};
    struct A2 : A {};
    
    void foo( A1 a1 ) {}
    
    int main() {
    	A2 a2;
    	foo( a2 ); //--> hier soll der Compiler einen Fehler melden
    }
    

    Edit: Oder suchst du das hier? http://drdobbs.com/184401633



  • Ich habe mir extra dafür mal vor Jahren diese Headedatei "type.h" angelegt:

    #ifndef TYPE_H
    #define TYPE_H
    
    #ifdef TEST_TYPE
    
    template<typename T, class NAME> class type
    {
    public:
    	typedef type<T, NAME> THIS;
    
    	type() {}
    	type(const THIS& t) { x = t.x; }
    	type(const T& _t) { x = _t; }
    
    	T value() const { return x; }
    	template<class U> U cast() const { return (U)x; }
    
    	THIS& operator  = (const THIS& t) { x  = t.x; return *this; }
    	THIS& operator *= (const THIS& t) { x *= t.x; return *this; }
    	THIS& operator /= (const THIS& t) { x /= t.x; return *this; }
    	THIS& operator %= (const THIS& t) { x %= t.x; return *this; }
    	THIS& operator += (const THIS& t) { x += t.x; return *this; }
    	THIS& operator -= (const THIS& t) { x -= t.x; return *this; }
    	THIS& operator <<=(const THIS& t) { x <<= t.x; return *this; }
    	THIS& operator >>=(const THIS& t) { x >>= t.x; return *this; }
    	THIS& operator &= (const THIS& t) { x &= t.x; return *this; }
    	THIS& operator |= (const THIS& t) { x |= t.x; return *this; }
    	THIS& operator ^= (const THIS& t) { x ~= t.x; return *this; }
    
    	const THIS& operator ++ () { ++x; return *this; }
    	const THIS& operator -- () { --x; return *this }
    	THIS operator ++ (int) { THIS t = *this; ++x; return t; }
    	THIS operator -- (int) { THIS t = *this; --x; return t; }
    
    	bool operator ==(const THIS& t) const { return x == t.x; }
    	bool operator !=(const THIS& t) const { return x != t.x; }
    	bool operator < (const THIS& t) const { return x <  t.x; }
    	bool operator <=(const THIS& t) const { return x <= t.x; }
    	bool operator > (const THIS& t) const { return x >  t.x; }
    	bool operator >=(const THIS& t) const { return x >= t.x; }
    
    	THIS operator * (const THIS& t) const { return THIS(x * t.x); }
    	THIS operator / (const THIS& t) const { return THIS(x / t.x); }
    	THIS operator % (const THIS& t) const { return THIS(x % t.x); }
    	THIS operator + (const THIS& t) const { return THIS(x + t.x); }
    	THIS operator - (const THIS& t) const { return THIS(x - t.x); }
    	THIS operator <<(const THIS& t) const { return THIS(x << t.x); }
    	THIS operator >>(const THIS& t) const { return THIS(x >> t.x); }
    	THIS operator & (const THIS& t) const { return THIS(x & t.x); }
    	THIS operator | (const THIS& t) const { return THIS(x | t.x); }
    	THIS operator ^ (const THIS& t) const { return THIS(x ^ t.x); }
    	THIS operator + () const { return THIS( x); }
    	THIS operator - () const { return THIS(-x); }
    	THIS operator ! () const { return THIS(!x); }
    	THIS operator ~ () const { return THIS(~x); }
    
    	friend bool operator ==(const T& _t, const THIS& t) { return _t == t.x; }
    	friend bool operator !=(const T& _t, const THIS& t) { return _t != t.x; }
    	friend bool operator < (const T& _t, const THIS& t) { return _t <  t.x; }
    	friend bool operator <=(const T& _t, const THIS& t) { return _t <= t.x; }
    	friend bool operator > (const T& _t, const THIS& t) { return _t >  t.x; }
    	friend bool operator >=(const T& _t, const THIS& t) { return _t >= t.x; }
    
    	friend THIS operator * (const T& _t, const THIS& t) { return THIS(_t * t.x); }
    	friend THIS operator / (const T& _t, const THIS& t) { return THIS(_t / t.x); }
    	friend THIS operator % (const T& _t, const THIS& t) { return THIS(_t % t.x); }
    	friend THIS operator + (const T& _t, const THIS& t) { return THIS(_t + t.x); }
    	friend THIS operator - (const T& _t, const THIS& t) { return THIS(_t - t.x); }
    	friend THIS operator <<(const T& _t, const THIS& t) { return THIS(_t << t.x); }
    	friend THIS operator >>(const T& _t, const THIS& t) { return THIS(_t >> t.x); }
    	friend THIS operator & (const T& _t, const THIS& t) { return THIS(_t & t.x); }
    	friend THIS operator | (const T& _t, const THIS& t) { return THIS(_t | t.x); }
    	friend THIS operator ^ (const T& _t, const THIS& t) { return THIS(_t ^ t.x); }
    
    private:
    	T x;
    };
    
    #define TYPEDEF(T, NAME)\
    	struct _S_##NAME\
    	{\
    		static const char * const name() { return #NAME; }\
    	};\
    	typedef type<T, _S_##NAME> NAME;\
    	/* partial template */\
    	template<class U> U CAST(const NAME& t)\
    	{\
    		return U(t.value()); /* t.template cast<U>(); */\
    	}
    
    #else
    
    #define TYPEDEF(T, NAME)\
    	typedef T NAME;
    
    template<class U, class T> U CAST(const T& t)
    {
    	return U(t);
    };
    
    #endif
    
    #endif
    

    Also anstatt typedef dann das Makro TYPEDEF benutzen:

    #define TEST_TYPE
    #include "type.h"
    
    TYPEDEF(A, A1)
    TYPEDEF(A, A2);
    

    (mittels des Makros "TEST_TYPE" kann diese Überprüfung dann aktiviert werden, z.B. nur im Debug-Modus)

    Und das Makro CAST(...) gibt es extra für den Fall, daß man dann doch explizit zwischen den Datentypen casten will.



  • n1 Th69!



  • hatte irgendwie gehofft, dass es anders geht, aber dann eben auf die harte Tour! Danke Th69



  • hatte irgendwie gehofft, dass es anders geht, aber dann eben auf die harte Tour! Danke Th69


Anmelden zum Antworten