2015-07-22 34 views
9

CRTP pattern, çok iş parçacıklı ortamlarda erişim eşitleme için bazı kilitleme mekanizmasıyla birlikte kullanmak istiyorum.Şablon dışı hatanın şablon tanımı

Benim kod şöyle görünür: derlerken

//-- CRTP base class with some sync/lock mechanism 
template<typename T, typename SYNC> 
struct Base { 
    static std::unordered_map<int, std::string> s_map; 
    static SYNC s_sync; 
}; 

//-- derived class using CRTP 
template<typename SYNC> 
struct ProductX : public Base<ProductX<SYNC>, SYNC> {}; 

//-- static initialisation 
template<typename SYNC> 
std::unordered_map<int, std::string> Base<ProductX<SYNC>, SYNC>::s_map { 
    { 1, "value_1" }, 
    { 2, "value_2" } 
} 

Ancak

error: template definition of non-template std::unordered_map<int, std::basic_string<char> > Base<ProductX<SYNC>, SYNC>::s_map

olsun.

Hata, statik s_map ilklendirmesi için yükseltildi. Birisi bana yanlış yaptığımı gösterir mi?

+0

@Deduplicator - Bu, işaretlediğiniz şeyin kopyası değildir. Eğer bir şeyin kopyası varsa, bundan sonra: http://stackoverflow.com/questions/13404695/c-how-to-initialize-static-variables-of-a-partial-template-specialization –

cevap

0

C++ Bu sağlar:

template<typename SYNC> 
std::unordered_map<int, std::string> Base<ProductX<SYNC>, SYNC>::s_map { }; 

sadece kısmi şablon sınıf uzmanlık karşılık gelen. Bunları yapmak için lütfen Columbo ve n.m. Aşağıdaki kullanıcılar. Bununla birlikte, dezavantaj, bu şekilde oluşturduğunuz her ProductX sınıfı için her şeyi yeniden tanımlamanız gerektiğidir. Yani. Benim durumumda, ProductX, ProductY, ProductZ sınıflarını oluşturmak istiyorsam, çok pratik IMHO olmayan tüm üye işlevleri de dahil olmak üzere her biri için kısmi uzmanlık tanımlamanız gerekecek.

template<typename T, typename SYNC> 
std::unordered_map<int, std::string> Base<T, SYNC>::s_map { }; 

veya tamamen özelleşmiş şablon tanımı:

struct NoSync { }; 
template<typename NoSync> 
std::unordered_map<int, std::string> Base<ProductX<NoSync>, NoSync>::s_map { }; 
biz bütün sınıf uzmanlık yazmak istemiyorum durumda

, hiçbir özellikli şablon tanımıyla ya statik değişkeni kullanmak zorunda

//-- CRTP base class with some sync/lock mechanism 
template<typename T, typename SYNC> 
struct Base { 
    static std::unordered_map<int, std::string> s_map; 
    static SYNC s_sync; 
    static std::string& value_name1(int value) { return s_map[value]; } 
}; 

//-- derived class using CRTP 
template<typename SYNC> 
struct ProductX : public Base<ProductX<SYNC>, SYNC> {}; 

struct NoSync {}; 

//-- static initialisation 
template<> 
std::unordered_map<int, std::string> Base<ProductX<NoSync>, NoSync>::s_map { 
    { 1, "value_1" }, 
    { 2, "value_2" } 
}; 

int main() { 
    ProductX<NoSync> p; 
    std::cout << "Value: " << p.s_map[1] << "\n"; 
    std::cout << "Value: " << p.value_name1(2) << "\n"; 
} 

Bu seferki:

İşte tam şablon uzmanlık ile tam bir örnektir iyi derler.

Columbo ve 'n.m'ye teşekkür ederim.'onların cevapları için ve doğru yönde bana işaret için! Cevaplarınızı seçerdim, ancak bu çözümü sınıf şablonu uzmanlığı yazmadan göstermek istedim.

+0

Col ** u ** mbo. Ortada bir tane var. – Columbo

+1

@Columbo [Sri Lanka] (https://en.wikipedia.org/wiki/Colombo) hayranı olmadıkça ... – Barry

+0

@Barry Araştırmayı takdir ediyorum ama benim adım hala Columbo. Sana 'Berry' demiyorum çünkü ben de hırsızlık yapmayı seviyorum. ;-) – Columbo

7

Sen s_map tanımında üyeleri uzmanlaşma olarak Base<ProductX<SYNC>, SYNC> kullanır, bu nedenle aslında Base (§14.5.5.3/1) 'in karşılık gelen kısmi ihtisas gerekir. Başka bir deyişle, , varolmayan bir kısmi uzmanlığın bir üyesini tanımlamaya çalışıyorsunuz. Bu uzmanlık sağlayan

Dene:

template<typename SYNC> 
struct ProductX; 

//-- CRTP base class with some sync/lock mechanism 
template<typename T, typename SYNC> 
struct Base {}; 
template<typename SYNC> 
struct Base<ProductX<SYNC>, SYNC> { 
    static std::unordered_map<int, std::string> s_map; 
    static SYNC s_sync; 
}; 

//-- derived class using CRTP 
template<typename SYNC> 
struct ProductX : public Base<ProductX<SYNC>, SYNC> {}; 

//-- static initialisation 
template<typename SYNC> 
std::unordered_map<int, std::string> Base<ProductX<SYNC>, SYNC>::s_map { 
    { 1, "value_1" }, 
    { 2, "value_2" } 
}; 

Demo.

+0

Cevabınız için teşekkür ederiz Columbo ! Haklısın ve doğru yöne işaret ettin. Bununla birlikte, şablon sınıfında uzmanlık yazımı, benim yarattığım her bir ProductX için her şeyi yeniden yazmak zorunda kaldığım için çok uygun değil. Daha fazla bilgi için aşağıdaki cevabımı inceleyin. –

4

Basitleştirilmiş bir örnek.

template <class A, class B> 
struct C 
{ 
    static int x; 
}; 

template <class A, class B> int C<A, B>::x = 0; // this works 

Ancak

template <class A> int C<A, double>::x = 0; // same error as yours 

ikinci tanım mevcut değildir C kısmi uzmanlık aittir. Bir tane daha oluşturun:

template <class A> 
struct C<A, double> 
{ 
    static int x; 
}; 

template <class A> int C<A, double>::x = 1; 

ve her şey tekrar iyidir.

+0

Cevabınız için teşekkürler! Columbo olarak, bana doğru yönde işaret ettin. Daha fazla bilgi için aşağıdan kendi yanıtıma bakın. –