2014-07-08 63 views
11

belli türleri için grup sınıf şablonu uzmanlık bir tekniktir/iyi tarzı var mı uzmanlıklara?Grup sınıf şablonu

Bir örnek: Bir sınıf şablonu Foo kullandığınızı varsayalım ve bunu harf ile

A = { Line, Ray } 

için ve dizgi B

B = { Linestring, Curve } 

için başka bir şekilde aynı uzmanlaşmış olması gerekir

şimdiye kadar ne yapıyorum:

(tekniği de fonksiyonlar için here sunulmuştur)
#include <iostream> 
#include <type_traits> 
using namespace std; 

// 1st group 
struct Line {}; 
struct Ray  {}; 
// 2nd group 
struct Curve  {}; 
struct Linestring {}; 

template<typename T, typename Groupper=void> 
struct Foo 
{ enum { val = 0 }; }; 

// specialization for the 1st group 
template<typename T> 
struct Foo<T, typename enable_if< 
    is_same<T, Line>::value || 
    is_same<T, Ray>::value 
>::type> 
{ 
    enum { val = 1 }; 
}; 

// specialization for the 2nd group 
template<typename T> 
struct Foo<T, typename enable_if< 
    is_same<T, Curve>::value || 
    is_same<T, Linestring>::value 
>::type> 
{ 
    enum { val = 2 }; 
}; 

int main() 
{ 
    cout << Foo<Line>::val << endl; 
    cout << Foo<Curve>::val << endl; 
    return 0; 
} 

Ekstra bir yardımcı yapı enable_for kodu kısaltır (ve kabul edilen türleri doğrudan yazmayı sağlar). Başka önerileriniz var mı, düzeltmeler? Bu daha az çaba gerektirmiyor mu?

+3

Ayrıca grup tarafından * a * type_traits oluşturabilir. – Jarod42

+0

@Angew: ah, ben baz şablonu kaçırdı. Haklısın, bunlar iki uzmanlık. –

cevap

13

Ayrıca kendi özellikleri ile ve enable_if olmadan yapabilirsiniz:

Bu otomatik olarak her tür en fazla bir grupta olmasını sağlama avantajına sahiptir
// Traits 

template <class T> 
struct group_number : std::integral_constant<int, 0> {}; 

template <> 
struct group_number<Line> : std::integral_constant<int, 1> {}; 

template <> 
struct group_number<Ray> : std::integral_constant<int, 1> {}; 

template <> 
struct group_number<Linestring> : std::integral_constant<int, 2> {}; 

template <> 
struct group_number<Curve> : std::integral_constant<int, 2> {}; 


// Foo 

template <class T, int Group = group_number<T>::value> 
class Foo 
{ 
    //::: whatever 
}; 

template <class T> 
class Foo<T, 1> 
{ 
    //::: whatever for group 1 
}; 

template <class T> 
class Foo<T, 2> 
{ 
    //::: whatever for group 2 
}; 

.

11

iki yeni tip özelliklerini kullanarak dolaylama Ekstra seviyesi: o zaman

template<class T> 
struct is_from_group1: std::false_type {}; 

template<> 
struct is_from_group1<Line>: std::true_type {}; 

template<> 
struct is_from_group1<Ray>: std::true_type {}; 

template<class T> 
struct is_from_group2: std::false_type {}; 

template<> 
struct is_from_group2<Curve>: std::true_type {}; 

template<> 
struct is_from_group2<Linestring>: std::true_type {}; 

ve bu türüne enable_if hala emin olun hiçbir kullanıcı tarafından buna ihtiyaç

// specialization for the 1st group 
template<typename T> 
struct Foo<T, typename enable_if< 
    is_from_group1<T>::value 
>::type> 
{ 
    enum { val = 1 }; 
}; 

// specialization for the 2nd group 
template<typename T> 
struct Foo<T, typename enable_if< 
    is_from_group2<T>::value 
>::type> 
{ 
    enum { val = 2 }; 
}; 

Not kişilik özellikleri do tanımlı sınıf her iki gruba eklenir veya bir belirsizlik alırsınız. Ya grup numarası N için std::integral_constant<int, N> kullanarak numaralı gruptan türetmek için Angew çözümüyle @ kullanabilirsiniz. bu grupların mantıksal olarak münhasır değilsen, sen buna karşı korur enable_if içine fazladan bir koşul ekleyebilirsiniz.