2015-07-19 9 views
14

Ben std::enable_if kullanarak çalışıyor şu durumda: Artıkyinelenmesi şikayetçi?

template<typename T, 
     typename std::enable_if<std::is_same<int, T>::value>::type* = nullptr> 
void f() { } 

template<typename T, 
     typename std::enable_if<std::is_same<double, T>::value>::type* = nullptr> 
void f() { } 

, ben cppreference içinde daha temiz Bence yeni sözdizimi, testere:

: Ben port için kodumu istediğini typename = std::enable_if_t<std::is_same<int, T>::value>>

template<typename T, 
     typename = std::enable_if_t<std::is_same<int, T>::value>> 
void g() { } 

template<typename T, 
     typename = std::enable_if_t<std::is_same<double, T>::value>> 
void g() { } 

Ama şimdi GCC (5.2) şikayet:

error: redefinition of 'template<class T, class> void g()' 
     void g() { } 

Neden böyle? Bu durumda yeni, daha özlü sözdizimine sahip olmak için ne yapabilirim? Bir ":: type" kaçırıyorsun

+5

İkinci kodunuz varsayılan şablon argümanlarını kullanır. Bunlar, işlev imzasının bir parçası değildir, dolayısıyla aynı imza = redefinition ile iki işlev şablonu bildiriyorsunuz. 'Enable_if_t' nin karşılık gelen kullanımı 'std :: enable_if_t :: value> * = nullptr' dir. – dyp

+0

Orijinal kodunuzu tam olarak yeniden yazmadınız. '* Nullptr'ı unuttun. –

+0

Bildirimlerden birine "kımıldama şablon parametresi ekleyebilirsiniz", örneğin, "enable_if" –

cevap

23

Biraz kodu kaldırmak edelim.

template< 
    class T, 
    class U/* = std::enable_if_t<std::is_same<int, T>::value>*/ 
> 
void g() { } 

template< 
    class T, 
    class U/* = std::enable_if_t<std::is_same<double, T>::value>*/ 
> 
void g() { } 

Derleyici yukarıdaki iki şablonu reddederse şaşırır mısınız?

Onlar "tip" template<class,class>void() her iki şablon işlevleri vardır. 2 tip argüman farklı varsayılan değer meseleleri değil sahip gerçeği. Bu, iki farklı print(string, int) işlevinin farklı varsayılan int değerleriyle aşırı yüklenmesini beklemek gibi olurdu.;) Elimizdeki İlk durumda

: Burada

template< 
    typename T, 
    typename std::enable_if<std::is_same<int, T>::value>::type* = nullptr 
> 
void f() { } 

template< 
    typename T, 
    typename std::enable_if<std::is_same<double, T>::value>::type* = nullptr 
> 
void f() { } 

biz enable_if maddesini kaldıramazsınız. enable_if_t için Güncellenmesi:

template< 
    class T, 
    std::enable_if_t<std::is_same<int, T>::value>* = nullptr 
> 
void f() { } 

template< 
    class T, 
    std::enable_if_t<std::is_same<double, T>::value>* = nullptr 
> 
void f() { } 

Ben de class ile typename bir kullanım yerini aldı. Şaşkınlığınızdan şüpheleniyorum çünkü typename'un iki anlamı vardır - biri bir çeşit template argümanı için bir marker, diğeri ise bağımlı tipte bir disambiguator.

Burada 2. argüman, türe ilk bağımlı olan bir göstergedir. Derleyici, bu iki çakışma olup olmadığını ilk önce T türünde değiştirmeden belirleyemez - ve bunların kesinlikle çakışmayacağını unutmayın.

-6

.. işlev döndürme türü için

template<typename T, 
      typename = std::enable_if_t<std::is_same<int, T>::value>::type> 
    void g() { } 

    template<typename T, 
      typename = std::enable_if_t<std::is_same<double, T>::value>::type> 
    void g() { } 
+2

'std :: enable_if_t'' std :: enable_if' 'iç içe geçmiş bir' '' '' tanımının bir takma ad şablonudır. –

2

, aşağıdaki aradığınız:

template<typename T> std::enable_if_t< conditional, instantiation result > foo(); 

Örnek:

#include <iostream> 

// when T is "int", replace with 'void foo()' 
template<typename T> 
std::enable_if_t<std::is_same<int, T>::value, void> foo() { 
    std::cout << "foo int\n"; 
} 

template<typename T> 
std::enable_if_t<std::is_same<float, T>::value, void> foo() { 
    std::cout << "foo float\n"; 
} 

int main() { 
    foo<int>(); 
    foo<float>(); 
} 

http://ideone.com/TB36gH

http://ideone.com/EfLkQy

6

enable_if_t<B> sadece typename enable_if<B>::type için bir takma ad olduğunu da görüyoruz. Ikimizde tip Xbağımlı üzerinde şablon parametreleri <typename, X*>, iki fonksiyon şablonları

template<typename T, 
     typename std::enable_if<std::is_same<int, T>::value>::type* = nullptr> 
void f() { } 

template<typename T, 
     typename std::enable_if<std::is_same<double, T>::value>::type* = nullptr> 
void f() { } 

template<typename T, 
     typename = typename std::enable_if<std::is_same<int, T>::value>::type> 
void g() { } 

template<typename T, 
     typename = typename std::enable_if<std::is_same<double, T>::value>::type> 
void g() { } 

f durumunda: en g yüzden biz f ve g arasındaki gerçek fark görebilirsiniz yerine edelim ilk şablon argüman türü. g durumunda biz şablon parametreleri <typename, typename> ile iki fonksiyon şablonları var ve C++ ikisi de aynı varlık beyan edildiğinin iddia edilmesi, böylece bağlıdır yalnızca varsayılan şablon argümandır.

Ya tarzı enable_if_t takma adı ile kullanılabilir:

template<typename T, 
     std::enable_if_t<std::is_same<int, T>::value>* = nullptr> 
void f() { } 

template<typename T, 
     std::enable_if_t<std::is_same<double, T>::value>* = nullptr> 
void f() { } 

template<typename T, 
     typename = std::enable_if_t<std::is_same<int, T>::value>> 
void g() { } 

template<typename T, 
     typename = std::enable_if_t<std::is_same<double, T>::value>> 
void g() { } 
+0

Katlılık cevaplarını kabul edebilirsem aynı şeyi kabul ettim çünkü aynı derecede geçerliydi! Teşekkürler ! –

+0

Sorun yok, Yakk'ın açıklaması biraz daha iyi. – Oktalist

İlgili konular