2012-11-24 23 views
5

Üzgünüz, bu genel bir soru gibi görünüyor, aradığım yanıtın cevabını bulana kadar bulamadım. En yakın sonrası olacağını bu bir: Template Specialization for basic POD onlyŞablon operatör yüklenmesinde aşırı yüklenme yok

ı bir sınıf template <class T> class A {...}; var ve ben bir iç ikili operatör (tip A iki nesne) olarak operatör + aşırı istiyoruz ve tip karma bir ikili operatör olarak (nesne diyelim A ve sayısal POD tipi).

#include <type_traits> 
using namespace std; 

// Declare/fine template 
template <class T> class A {...}; 

// Internal binary operator 
template < class T, class U > 
    A< typename common_type<T,U>::type > 
operator+ (const A<T> &a, const A<U> &a) { ... } 

// Mixed binary operator 
template < class T, class U > 
    A< typename common_type<T,U>::type > 
operator+ (const A<T> &a, const U &b) { ... } 

Ama ikinci tanım ilkinden çatışma halinde olduğu gibi o zaman görünüyor:

İdeal olarak, yazdıklarıma istiyorum olduğunu. İkinci tanımı kullanarak, U'nun sayısal bir POD tipi olduğundan emin olmanın yolunu biliyorum. Eğer bu şekilde gidersem sorun şu ki, eğer temelde A şablonunda bulunan altta yatan şablon tipinin ne olduğunu bilmemizin bir yolu yok.

Lütfen bana sorumun yeterince açık olup olmadığını söyle ve şimdiden teşekkürler! :)

DÜZENLEME: Şablon belirtimi, son filtremde "A<T> ise U" ifadesiyle silinmiştir. Kısacası, T'nin saklı olduğunu söylüyorum. Bu hemen canlı kümesinden ikinci aşırı dışlar

#include <type_traits> 


// "A" template  

template <typename> class A {}; 


// Traits for "A-ness": 

template <typename> struct is_a : std::false_type { }; 
template <typename T> struct is_a<A<T>> : std::true_type { }; 


// Operators: 

template <class T, class U> 
A<typename std::common_type<T, U>::type> 
operator+(const A<T> & a, const A<U> & b); 

template <class T, class U, 
      typename = typename std::enable_if<!is_a<U>::value>::type> 
A<typename std::common_type<T, U>::type> 
operator+(const A<T> & a, const U & b); 

ve getiri belirleme yüzden sorun:

+0

'şablon U> :: değeri geçersiz> :: türü> bir :: türü> işleç + (const A & a, const U &b); 'hile yapmalıdır. – Morwenn

+0

" Altta bulunan şablon türü "ile ne kastediliyorsunuz? Dahili kullanıcı olduğu için, karışık işleç, U'nun" A "olması durumunda seçilemez Daha iyi bir eşleşme. İç operatörde 'A < A> 'davayı ele almak ister misiniz? – pmr

+0

Yardımlarınız için hepinize teşekkür ederiz. pmr, haklısınız, sorun aslında daha önce gerçekleşir, çünkü common_type. 'A ' ve U arasında yazıyoruz, biz En iyi maçtan önce bortu değerlendirilebilir. Morwenn, çözümün denediğim bir şeye benziyor, ama bu bağlamda yanlış; S ile 'A ' olabilir!= T ve hala operasyonu yapabilmem gerekir. – Sheljohn

cevap

2

Bunu daha genel türlerinden A ait uzmanlık ayırt etmek için bir küçük yardımcı özelliği ile çalışmak yapabilirsiniz İkinci aşırı yükün türü, sadece ilk istendiğinde asla ortaya çıkmaz.

(Bu aşırı yük setini kontrol etmek temerrüde şablon argümanları içinde enable_if kullanarak bir örnektir.)

+0

Sen bir hayat kurtarıcısın :) Bu "şablon programlama" hilelerinde yeniyim, bence tam olarak ihtiyacım olan şey bu. Test edeyim ve cevabı doğrularım. Tekrar teşekkürler! – Sheljohn

+0

Çalışıyor, çok teşekkürler! :) – Sheljohn

1

Sen common_type bir SFINAE dostu yazabilirsiniz - Kampta şahsen olduğumu özellikler gerektiği hemen her zaman SFINAE . Şöyle ki:

Şimdi
// Black hole metafunction that eats everything 
template<typename...> struct void_ { using type = void; }; 

template<typename... T> 
using Void = typename void_<T...>::type; 

// Due to std::common_type being variadic we need to 
// pass a variadic pack around 
template<typename... T> struct list {}; 

// Actually defined, but with no member types for SFINAE purposes 
template<typename Sequence, typename Sfinae = void> 
struct common_type_impl {}; 

template<typename... T> 
struct common_type_impl<list<T...>, Void<typename std::common_type<T...>::type>> 
: std::common_type<T...> {}; 

template<typename... T> struct common_type: common_type_impl<list<T...>> {}; 

, aşırı yük yerine gürültüyle şikayet adaylar listesinden silinecektir A<T> ve U arasında hiçbir ortak türü yoktur.

Ayrıca, DR 2141 numaralı belgede belgelendiği gibi, kendi başına sorunları olan sonuç olarak, std::common_type'u değiştirmek de mümkündür. Değiştirmeyi özetlemeyeceğim çünkü daha iyi bir çözümün ne olduğu belli değil, özellikle de DR'nin önerilen çözümünün daha kötü olduğunu düşünüyorum.

+0

Bu yüzden burada ne olduğunu doğru bir şekilde anladığımdan emin olmak için, aslında onu oldukça zor buluyorum; kodumdaki common_type'ın bu yeni sürümünü kullandığımda, tanımlanmış bir ortak türle bir kez söyleyin ve bir kez bile SFINAE aslında kendi kodumda gerçekleşecektir .. bu sizin cümleniniz "Şimdi, ne zaman ..." " sağ? Ve eğer ortak bir tip yoksa, iki uygulamadan hiçbiri için, artık bir SFINAE durumunda değiliz ve bu durumda bir derleme zamanı hatası üretecek, doğru (bis)? – Sheljohn

+0

@ Sh3ljohn 'Bir kez' ile ne demek istediğimi takip etmiyorum - bu, std :: common_type'nın bir yerine koymasıdır ve tamamen bunun içindedir. 'Std :: common_type' öğesini nerede kullanırsanız kullanın, bunun yerine bunu kullanın: tam olarak aynı anlama gelir ve aynı zamanda her zaman bir hatadan ziyade yumuşak bir hatayla sonuçlanır. Bu açık uzmanlık ile ilgili ise, o zaman yapılacak özel bir şey yoktur - 'std :: common_type' için açık uzmanlık yazın ve bu da onları seçecektir. –

+0

Evet Ne yaptığı var. Benim durumumda (orijinal kaynaklara bakınız), bir şablon uzmanlığı, operatörün şablon aşırı yüklenmesinden fazla değil; 'ile bir kez' beyanlardan birine başvurdu. Ben sadece öneri, operatörün geçerli türlerle çağrılması sırasında "B " türünün geçmesiyle sonuçlanan "birbirini dışlayan" bir davranışla sonuçlanacağından emin olmak istiyorum. – Sheljohn

İlgili konular