şablon sınıfı üye işlevinin açık uzmanlığı


88

Bir tür için şablon üye işlevini uzmanlaştırmam gerekiyor ( çift diyelim ). Sınıfın Xkendisi bir şablon sınıfı olmadığında iyi çalışıyor , ancak onu şablon yaptığımda GCC derleme zamanı hataları vermeye başlıyor.

#include <iostream>
#include <cmath>

template <class C> class X
{
public:
   template <class T> void get_as();
};

template <class C>
void X<C>::get_as<double>()
{

}

int main()
{
   X<int> x;
   x.get_as();
}

işte hata mesajı

source.cpp:11:27: error: template-id
  'get_as<double>' in declaration of primary template
source.cpp:11:6: error: prototype for
  'void X<C>::get_as()' does not match any in class 'X<C>'
source.cpp:7:35: error: candidate is:
  template<class C> template<class T> void X::get_as()

Bunu nasıl düzeltebilirim ve buradaki sorun nedir?

Şimdiden teşekkürler.


2
Bu uzmanlaşmak, cari standardında yasadışı, siz de sınıf uzmanlaşmak zorunda ...
Nim

ancak sınıf şablon değilse çalışır. Yasadışı mı?
ledokol

hayır, bu tamamen iyi, yalnızca bu kuralın geçerli olduğu sınıf şablonları için (AFAIK).
Nim

Yanıtlar:


108

O şekilde çalışmıyor. Sen aşağıdakileri söylemek gerekir, ama öyle değil doğru

template <class C> template<>
void X<C>::get_as<double>()
{

}

Açıkça uzmanlaşan üyelerin , çevreleyen sınıf şablonlarının da açıkça uzmanlaşması gerekir. Bu nedenle, yalnızca üyeyi uzmanlaştıran aşağıdakileri söylemeniz gerekir X<int>.

template <> template<>
void X<int>::get_as<double>()
{

}

Çevreleyen şablonu uzmanlaşmadan tutmak istiyorsanız, birkaç seçeneğiniz vardır. Aşırı yüklenmeyi tercih ederim

template <class C> class X
{
   template<typename T> struct type { };

public:
   template <class T> void get_as() {
     get_as(type<T>());
   }

private:
   template<typename T> void get_as(type<T>) {

   }

   void get_as(type<double>) {

   }
};

neden type<>sarmalayıcıya ihtiyacınız var ? bir işaretçi tipine 0 atışı Thile yapamaz mıydı? Sanırım o kadar zarif değil ...
Nim

Görünüşe göre bunu yapmak gerçekten mümkün değil. Teşekkürler.
ledokol

3
@Nim haklısın, işaretçi atma olayının çirkin olduğunu düşünüyorum ve işaretçi oluşturamayacağınız türler için işe yaramaz (referanslar). Ayrıca, bir işlev parametresinin boyutu olmayan bir dizi türüne işaretçi olması C ++ 'da geçersizdir. Bir tür sarıcıda olması, tüm türler için çalışmasını sağlar.
Johannes Schaub -

2
@ JohannesSchaub-litb: Aşırı yüklemelerdeki diğer seçenekler nelerdir? Bazılarını gösterebilir misin?
Jean-Bernard Jansen

2
@ fast-reflexes onun yorumu template<typename T> void get_as(T*); void get_as(double*);a (T*)0.
Johannes Schaub -

25

Biri kullanılabilirse std::enable_ifSFINAE'ye güvenebiliriz (ikame hatası bir hata değildir)

bu böyle çalışır (bkz CANLI ):

#include <iostream>
#include <type_traits>

template <typename C> class X
{
public:
    template <typename T, 
              std::enable_if_t<!std::is_same_v<double,T>, int> = 0> 
    void get_as() { std::cout << "get as T" << std::endl; }

    template <typename T, 
              std::enable_if_t<std::is_same_v<double,T>, int> = 0> 
    void get_as() { std::cout << "get as double" << std::endl; }
};

int main() {
   X<int> d;
   d.get_as<double>();

   return 0;
}

İşin çirkin tarafı, tüm bu enable_if'lerin derleyici için tek bir uzmanlığının bulunması gerektiğidir, aksi takdirde belirsizlik giderme hatası ortaya çıkacaktır. Bu nedenle, "T olarak al" varsayılan davranışı aynı zamanda eğer bir etkinleştirme gerektirir.


Daha modern hale getirmek için yayını güncelledi.
Gabriel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.