2011-12-10 27 views
5

Ben bu işi yapmak için ne yapabilir: etmiyor ki,Kendine referans Şablon

unknown type name 'Test' 

Şimdilik kendine referans şablon: bu bana derleyici hata veriyor

template<class C, class V, Test V::*> 
class Test { 
}; 

Mümkün değil. Çalışması için ne yapılabilir?

DÜZENLEME:

İşte bu ihtiyaç yapardım. En az minimum kodlama çabasıyla iki yönlü (düşün ebeveyn-çocuk) ilişki şemasını uygulamak istiyorum.

template <class O, class T, Reference<T, O, Reference O::*> T::* opposite> 
class Reference 
{ 
    T **data; 
    int count; 
public: 
    Reference(): data(new T*[N]), count(0) {} 
    ~Reference() {delete[] data;} 
    Reference &add(T *t) { 
     handleOtherSide(); 
     return link(t); 
    } 
    // a lot of stuff to implement this 
}; 

Bu koleksiyon sınıfıdır. Burada kullanılacak gibi olacaktır:

class Partner 
{ 
public: 
    Reference<Partner, Address, &Address::partner> addresses; 
}; 

class Address 
{ 
public: 
    Reference<Address, Partner, &Partner::addresses> partner; 
}; 

Amacım Referans Ortağı ve Adres (şu anda ben tedarik gibi sınıflar için kurucular sağlamak için gerek yoktur, böylece şablon argüman olarak sağlanacak çalışması için gerekli her şeye sahip olmaktır Bir yapıcı arg olarak karşıt üye işaretçisi, ancak bu katılımcı sınıfları için açık yapıcılara sahip olmamı gerektirir). Referans sınıfına bir "sahip" işaretçisini de girmemeli veya hesaplamam gerekir. Bu problemi burada bıraktım çünkü kendi kendini referanslayan şablona odaklanmak istiyorum.

Bunu düşünmenin en kolay yolu, destek olur: bimap. Ama bimap ile ilgili problem, kapama bimapını istemiyorum ama sadece sol ve sağ kısımları. Bimap da uygun değildir, çünkü belirli bir ilişkinin bütün ilişkilerini yöneten tek bir bimap'a yol açacaktır. Üzerinde işlemlerin yavaşlatılması çok sayıda nesne tutabilir.

+2

Bu ne için? Bunu, kendi kendini referans alandan başka bir şekilde uygulamak çok daha basit. – Jon

+5

Bu soruyu, 666 saygınlık sayımını elde etmek için atmalıydım. –

+2

Böyle bir özyinelemeli şablonla elde etmeye çalıştığınız amaç, sormama neden olursa, nedir? – dasblinkenlight

cevap

1

sorun, ne ben başarmak istiyorum (okuyun: Üye başına tek satır kod) en azından şablonlar ve kod miktarını ve ben amaçlayan ediyorum sınıfları ile, C++ mümkün değildir. İleriye yönelik bildirimlere ve tam tanımlı türlere ihtiyaç duyan derleyici ile başlar; bu, değer-değer üyeler ve bu imkansız olan şablon argümanlarını (döngüsel bağımlılıklar durumunda) yapar. O zaman, bu üyenin sınıfı henüz tam olarak tanımlanmadığında, bir üye argümanının bir şablon argümanı olması mümkün değildir. Tüm bunların temel nedeni, derleyicinin nasıl çalıştığıdır: tek geçiştir. Ve bunun için yapabileceğim hiçbir şey yok.

Çözüm, şablonlardan kaçınmak için referans olarak üyeler veya bir OO stili temel sınıfı veya bir destek :: herhangi bir stil kapsayıcı kullanmaktır. İkinci 2 ile, değere sahip üyelere sahip olmak mümkün olabilir.

2

Böyle bir şey mi arıyorsunuz? O değil kendinden referanslı şablon, ama

template< typename PType, typename PDerived > 
class TBase 
{ 
    //do stuff with TDerived 
public: 
    bool foo(void) 
    { 
    return (static_cast< PDerived* > (this)->bar()); 
    } 
}; 

template< typename PType > 
class TDerived : public TBase< PType, TDerived<PType> > 
{ 
    friend class TBase< PType, TDerived<PType> > ; 
    //do stuff 
protected: 
    bool bar(void) 
    { 
    return (true); 
    } 
}; 

DÜZENLEME çıkmış yöntemleri vb .: çağırabilir temel sınıf ve temel sınıf için bir şablon türü olarak türetilmiş bir sınıf belirtebilirsiniz: son ne Bir kez daha, emin değilim hedef. İstediğinizi düşündüğüm bir çözüm ya da en azından tasarımınızı uygulamak için kullanabileceğinize dair bir ipucu. Verdiğim tek gereksinim, hem hem de TPartner'un aynı ada sahip işlevi olmasıdır. Bak, ihtiyacın olan buysa. Prensip olarak, bir yardımcı sınıf oluşturabilir ve bir işaretçi aracılığıyla üye işlevine erişmek için CRTP'yi kullanabilirsiniz, ancak aslında ona ihtiyacınız olduğunu düşünmüyorum.

template< typename PType1, typename PType2 > 
class TReference 
{ 
public: 
    int mFlag; 

    TReference() : 
    mFlag(0) 
    { 
    } 
    TReference(int fFlag) : 
    mFlag(fFlag) 
    { 
    std::cout << "Creating reference " << PType1::sName << " -> " << PType2::sName << "." << std::endl; 
    } 
    TReference< PType2, PType1 > AccessOpposite(void) 
    { 
    PType2 lTmp; 
    lTmp.Opposite(); 

    return TReference< PType2, PType1 > (-1); 
    } 
}; 

class TPartner; 

class TAddress 
{ 
public: 
    static const char* sName; 
    TReference< TAddress, TPartner > mRef; 

    void Opposite(void) 
    { 
    std::cout << sName << "::Opposite" << std::endl; 
    } 
}; 

class TPartner 
{ 
public: 
    static const char* sName; 
    TReference< TPartner, TAddress > mRef; 

    TReference< TAddress, TPartner > Opposite(void) 
    { 
    std::cout << sName << "::Opposite" << std::endl; 
    } 
}; 

const char* TAddress::sName = "TAddress"; 
const char* TPartner::sName = "TPartner"; 

int main(void) 
{ 
TAddress lAddress; 
TPartner lPartner; 

std::cout << lAddress.mRef.mFlag << " " << lPartner.mRef.mFlag << std::endl; 

lPartner.mRef = lAddress.mRef.AccessOpposite(); 

std::cout << lAddress.mRef.mFlag << " " << lPartner.mRef.mFlag << std::endl; 

return (0); 
} 
+0

Oldukça ilginç ve eğlenceli görünüyor. Temel sınıf düzeyinde üye çubuğu() bildirmek değil mi? –

+0

Evet, şablon işlevlerinin başlatılma biçimi nedeniyle sorun yok. 'foo' aslında kod olarak adlandırılana kadar ve TDerived'in zaten tanımlandığı zamana kadar başlatılmayacaktır. Daha fazla bilgi almak için CRTP'yi arayın. – lapk

+0

Birkaç günlüğüne baktıktan sonra bunun benim problemimi nasıl çözebileceğini söylemem gerekiyor. Belki de çözümümüzü görebilmem için örneğimi biraz daha benimseyebilirsin? –

İlgili konular