Soru Şablon işlevinde bildirilmemiş bir değişken yasal kullanıyor mu?


Not: Orijinal sorun, büyük ölçüde makroları kullanır, ancak bu soru için basitleştirilmiştir.

Soru

// header.hpp
template <typename T>
void foo()
{
   someBoolean = true ; // at this point "someBoolean" wasn't
}                       // declared

Daha sonra, aşağıdaki kaynakta kullanılır:

// source.cpp
#include "header.hpp"

static bool someBoolean = false ;

void bar()
{
   foo<char>() ; // here, we call/instantiate the function
}

Bazı derleyicilerde (Windows, önceki Solaris) çalışır. Ve mevcut C ++ 11'in etkinleştirilmiş Solaris derleyicisinde, bazıBoolean undefined olduğunu söyleyerek başarısız oluyor.

Standartlara göre, templated bir kod, daha sonra kaynakta ilan edilen bir değişken kullanır (umarız!).

Bonus soru

Şablon, her biri kendi boole değişkeni olan ve şablonu başlatan, birden çok kaynağa dahil edilmesi beklenen bir başlıkta tanımlanır.

Her bir çeviri biriminde, şablonun, çeviri biriminin statik boole değişkeni etkilemesi bekleniyordu.

Şablonun tek bir tipte (örneğin "char") her örneğinin farklı değişkenleri etkilemesi beklenir.

Tanımsız davranışlara güvenmiyor muyuz?


23
2018-04-09 14:51


Menşei


“Her çeviri biriminde şablonun, çeviri biriminin statik boole değişkeni etkilemesi bekleniyordu.” Bu beklenti yanıltıcıdır. Windows'da bile kırık iki aşamalı arama ile, bu garanti edilmez. - Ben Voigt
İki aşamalı bir aramayı görmezden gelseniz bile, hala kırılmalar şu şekildedir: "Herhangi bir şablon için bir uzmanlık, çoklu çeviri birimlerinde anlık puanlara sahip olabilir. Eğer iki farklı örnekleme noktası bir tanım özelliğine (3.2) göre şablon uzmanlığı farklı anlamlar veriyorsa, program kötü biçimlendirilmiş, tanı gerekli değildir." - Ben Voigt
@BenVoigt: Yorumlar yerine tam tırnak ile gerçek bir cevap yazmalısınız. Onu seçip seçebilirim ... :-) - paercebal
Benim zamanım yok :( Bir başkası bunu yapmaktan hoşlanır. - Ben Voigt
@BenVoigt: Tamam. Detaylar ve alıntılar için çok teşekkürler. Takdir edildi. - paercebal


Cevaplar:


Bunun iki aşamalı arama ile ilgisi var. Kısa versiyon, herhangi bir isim değil şablon parametresine bağlı someBoolean burada) şablon tanım süresine bakılacaktır. Bu, Solaris derleyicisinin kodu reddetmede doğru olduğu anlamına gelir. someBoolean şablon tanımlanmadan önce tanımlanmamıştır.

Şablon parametresine bağlı olan adlar (ör. T::someBoolean = true) derleyicinin ne olduğunu bilmesine kadar geçerlilikleri belirlenemediğinden, şablon örnekleme zamanına ertelenecektir. T olduğunu. MSVC, bu iki aşamalı semantiği düzgün bir şekilde (en azından tarihsel olarak) uygulamamakla bilinir, bu nedenle kodunuz burada çalışır. Yine de, C ++ değil ve taşınabilir davranış değil.

C ++ standardının (bilinmeyen versiyonunun) Bölüm 14.6'sı (muhtemelen taslak):

Eğer bir isim bir şablon parametresine bağlı değilse (14.6.2'de tanımlandığı gibi), bu isim için bir beyan (veya beyannameler), ismin şablon tanımında göründüğü noktada kapsam dahilinde olacaktır; isim, o noktada bulunan deklarasyona (veya beyanlara) bağlıdır ve bu bağlanma, somutlaşma noktasında görülebilen beyanlarla not ected not not not not not not not not not not not not not not not.

(Aşağıdaki @BenVoigt yorum yoluyla)


24
2018-04-09 15:00



İşte, bu davranışı yaratan 14.6 bölümünün tam metni şu şekildedir: "Eğer bir isim şablon parametresine bağlı değilse (14.6.2'de tanımlandığı gibi), bu isimle ilgili bir beyan (veya beyannameler) adın şablon tanımında göründüğü nokta, isim o noktada bulunan deklarasyona (veya beyanlara) bağlıdır ve bu bağlanma, somutlaştırma noktasında görülebilen bildiriler tarafından not ff ff ff ff not not not not not not not not not not not not "" "" ". - Ben Voigt
Teşekkürler. Yasal olanı aramak için zamanım yoktu. - CAdaker
Her ikisi de taslak n3485 ve n4296, C ++ 14 versiyonunu yaptığına inandığım aynı dili içerir. - Ben Voigt
Bonus bilgisi: C ++ 98 standardı, 14.6.2 / 9'da (C ++ 14 standardında 14.6.2 / 10 yerine) aynı şeyi söyler, bu yüzden bu yeni bir şey değildir ve bazılarımız için geçerlidir. (eski) derleyiciler. - paercebal