Tür olmayan şablon parametreleri


93

Tür olmayan şablon parametresinin sabit bir integral ifadesi olması gerektiğini anlıyorum. Birisi ışık tutabilir mi, neden böyle?

template <std::string temp>
void foo()
{
     // ...
}
error C2993: 'std::string' : illegal type for non-type template parameter 'temp'.

Sabit bir integral ifadenin ne olduğunu anlıyorum. std::stringYukarıdaki kod parçacığındaki gibi sabit olmayan türlere izin vermemenin nedenleri nelerdir ?


17
Derleme zamanında bir şablon parametresi çözümlenir.
Etienne de Martel

Yanıtlar:


122

Bunu yapamamanızın nedeni, sabit olmayan ifadelerin derleme sırasında ayrıştırılıp değiştirilememesidir. Çalışma zamanı sırasında değişebilirler, bu da çalışma sırasında yeni bir şablonun oluşturulmasını gerektirir, bu mümkün değildir çünkü şablonlar bir derleme zamanı kavramıdır.

Standart, tip dışı şablon parametreleri için izin verdiği şeydir (14.1 [temp.param] p4):

Tür olmayan bir şablon parametresi aşağıdaki (isteğe bağlı olarak cv nitelikli) türlerden birine sahip olmalıdır:

  • integral veya numaralandırma türü,
  • nesneye işaretçi veya işleve işaretçi,
  • nesneye lvalue referansı veya fonksiyona lvalue referansı,
  • üyeye işaretçi,
  • std::nullptr_t.

6
@ALOToverflow: Bu, "üyeye işaretçi" nin altına düşer. Ya "üye işlevine işaretçi" ya da "üye verisine işaretçi" dir.
Xeo

4
Nesnelere (veya örnek alanlarına) işaretçiler söz konusu olduğunda, nesnelerin statik depolama süresine ve bağlantısına (C ++ 11 harici, C ++ 11'de dahili veya harici) sahip olması gerektiğine dikkat etmek önemlidir. derleme zamanında oluşturulabilir.
Theodore Murdock

2
C ++ 20'de, türün güçlü yapısal eşitliğe sahip olması, değişmez / değişken alt nesneler olmaması ve uzay gemisi operatörünün kamuya açık olması koşuluyla artık buna izin verilmektedir.
Rakete1111

74

Buna izin verilmez.

Ancak buna izin verilir:

template <std::string * temp> //pointer to object
void f();

template <std::string & temp> //reference to object
void g();

C ++ Standardında (2003) §14.1 / 6,7,8'e bakınız.


İllüstrasyon:

template <std::string * temp> //pointer to object
void f()
{
   cout << *temp << endl;
}

template <std::string & temp> //reference to object
void g()
{
     cout << temp << endl;
     temp += "...appended some string";
}

std::string s; //must not be local as it must have external linkage!

int main() {
        s = "can assign values locally";
        f<&s>();
        g<s>();
        cout << s << endl;
        return 0;
}

Çıktı:

can assign values locally
can assign values locally
can assign values locally...appended some string

7
@Mahesh: Çünkü şablonun temelde üzerinde bulunduğu şey, o std::stringişaretçinin veya referans nesnenin adresidir . Bu değişken yerel olsaydı, işlev her çağrıldığında muhtemelen farklı adresler alırdınız.
Xeo

11
@Mahesh: Derleme sırasında çağrı yığınının neye benzediğini bilmiyorsunuz. İşlevinizden önce, 10 veya diğer 3 veya daha fazla sayıda çağrılmış olabilirdi, bu nedenle dizenin oluşturulduğu yığındaki adres çağrıdan çağrıya değişebilir. Dış bağlantılı bir nesneye sahip olduğunuzda, adresi derleme / bağlantı sırasında sabitlenir.
Xeo

2
@Xeo " adresi derleme / bağlantı sırasında sabittir. " Yeniden konumlandırılabilir veya konumdan bağımsız kod için değil.
wonderguy

1
Bu yanıt (şu anda), bu davranışın neden var olduğunu soran OP'nin sorusuna değinmiyor gibi görünüyor ; bu cevap, herhangi bir açıklama sunmadan sadece OP'nin örneğini yeniden ifade etmektedir.
Quuxplusone

1
Partiye geç kaldım, görünüşe göre akıllı işaretçiler de işe yaramıyor
Nicholas Humphrey

28

Şablon argümanlarını karıştırabilmeniz gerekir

template <std::string temp>
void f() {
 // ...
}

f<"foo">();
f<"bar">(); // different function!?

Şimdi bir impl, bir std::stringveya, bu nedenle, herhangi bir başka rasgele kullanıcı tanımlı sınıf için, belirli bir değeri depolayan, uygulama tarafından anlamı bilinmeyen benzersiz bir karakter dizisi ortaya çıkarmalıdır . Ek olarak, rastgele sınıf nesnelerinin değeri derleme zamanında hesaplanamaz.

Sabit ifadelerle başlatılan C ++ sonrası sonrası için şablon parametre türleri olarak değişmez sınıf türlerine izin verilmesi planlanmaktadır. Bunlar, veri üyelerinin değerlerine göre yinelemeli olarak karıştırılmasıyla karıştırılabilir (temel sınıflar için, örneğin önce derinlik, soldan sağa geçiş uygulayabiliriz). Ama keyfi derslerde kesinlikle işe yaramayacak.


10

Bir şablon bağımsız değişken listesi içinde sağlanan tür olmayan bir şablon bağımsız değişkeni, değeri derleme zamanında belirlenebilen bir ifadedir. Bu tür argümanlar şöyle olmalıdır:

sabit ifadeler, fonksiyonların veya harici bağlantılı nesnelerin adresleri veya statik sınıf üyelerinin adresleri.

Ayrıca, dize değişmezleri dahili bağlantıya sahip nesnelerdir, bu nedenle bunları şablon bağımsız değişkenleri olarak kullanamazsınız. Global bir işaretçi de kullanamazsınız. Açıkça yuvarlama hataları olasılığı göz önüne alındığında, kayan noktalı değişmez değerlere izin verilmez.


Bir alıntı kullandın, peki kaynak nedir? Alıntı için bir kaynağı varsa, ona oy vermek isterim.
Gabriel Staples
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.