2015-01-24 47 views
10

sarılmış da hazırlar zaman: (1) bir unique_ptr ya yardımcı olmaz kullanmabariz derleme hatası ile, bu kodu düşünün şablona

struct A; 
struct B { 
    B() { new A(); } // error: allocation of incomplete type 'A' 
}; 

: (2)

struct A; 
struct B { 
    B() { std::make_unique<A>(); } // error: due to ~unique_ptr() 
}; 

Sonra (benim için büyük sürpriz) Ben öğrendim ki bu olacak derleme: (3)

struct A; 
struct B { 
    B() { std::make_unique<A>(); } 
}; 
struct A {}; // OK, when a definition is added **below** 

Sonra bu yanı new yardımcı olur olsun, kontrol - Hayır'ı: Bir template yapar içeride new sarılması: (4)

struct A; 
struct B { 
    B() { new A(); } // error: allocation of incomplete type 'A' 
}; 
struct A {}; 

Ben template s ve aslında bir ilgisi vardır düşündüm derleme: (5)

template <typename T> 
T* my_new() { return new T(); } // OK, when wrapped in template 
struct A; 
struct B { 
    B() { my_new<A>(); } 
}; 
struct A {}; 

Ve bütünlüğü sağlamak için

, A tanımını çıkarılması yine bir hata yükseltir: (6)

template <typename T> 
T* my_new() { return new T(); } // error: allocation of incomplete type 'A' 
struct A; 
struct B { 
    B() { my_new<A>(); } 
}; 
// do note: definition of A removed 

Neler oluyor burda? Ben 'u anladığım kadarıyla, derleyicisi, A'un boyutunu/tanımını ayırmak için ayırır, böylece yalnızca bildirmek yeterli değildir. Ayrıca, inanıyorum ki, bu tanım numaralı numaralı tahsisattan önce gelmelidir.

(1,4) 'ü kullanırken bu doğru gibi görünüyor. Ancak new sarıldığında, yanıldığımı görüyorum (2,3,5,6). Ben bugüne kadar bulunmuş

Olası açıklamalar şunlardır: template örnekleme gerçekleşene kadar tamamlanmış türleri için

  • onay gecikir. Bunun doğru olduğunu düşünüyorum, fakat benim durumumdakullanımı ve my_new<A>() numaralı çağrı neredeyse aynı konumda gerçekleşiyor. Yani bu sebep olamaz. Sağ?
  • Eksik olmayan türleri template olarak kullanma Bağımsız değişkenler tanımsız davranışı olabilir. Bu gerçekten doğru mu? Tüm uyarıları etkinleştirirken bile derleyici şikayette bulunmayacaktır. Ayrıca 5 ve 6'yı karşılaştırmak, derleyicinin aşağıdakileri tanımlayabilecek kadar akıllı olduğunu ve bu tanımın aşağıdaki gibi gerçekleştiğini düşündürmektedir (bu da neredeyse tamamlanmış halidir).

Neden 4 yanlış yazılmış olarak değerlendirilirken, 5 derleme (veya 5 tanımsız davranışı sadece yanlış bir şekilde derleme [ama sonra 3 kusurlu olmalı, değil mi?])?

arada: ++ clang test - 3.5.0 ve g ++ - 4.9.2

+0

http://blog.llvm.org/2009/12/dreaded-two-phase-name-lookup.html – OmnipotentEntity

+0

Belirsiz olması durumunda, bu makale yalnızca iki fazlı isim aramanın daha sıkı olan tarafını ele aldığından, şablon adları koddan başka bir geçiş yapana kadar örneklenmez, zaten geçtikten sonra 'A' tanımını okuduktan sonra derler. – OmnipotentEntity

+1

Bu, çeviri biriminin sonuna kadar şablon örneklemesini geciktirmek için yaygın bir uygulama tekniğidir. Kodunuz kötü biçimlendirilmiş, teşhis gerektirmez. –

cevap

6

§14.6.4.1 [temp.nokta]/p1,8, vurgu benim:

iki B tanımının sonunda my_new<A> bir nesnelleştirilmesi noktaları ve geçiş birimi sonunda bir bulunmaktadır

1 For a function template specialization, a member function template specialization, or a specialization for a member function or static data member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization and the context from which it is referenced depends on a template parameter, the point of instantiation of the specialization is the point of instantiation of the enclosing specialization. Otherwise, the point of instantiation for such a specialization immediately follows the namespace scope declaration or definition that refers to the specialization.

8 A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation. A specialization for a class template has at most one point of instantiation within a translation unit. A specialization for any template may have points of instantiation in multiple translation units. If two different points of instantiation give a template specialization different meanings according to the one definition rule (3.2), the program is ill-formed, no diagnostic required.

. Bu iki nokta farklı anlamlara neden olacağından (snippet 3 ve 5 için), program kötü biçimlendirilmiş NDR'dir (yani tanımlanmamış bir davranışa sahiptir).

+0

Farklı anlamlara sahip olan (3) ve (5) 'in her ikisinde de aynı anlamı taşıyan (6) aynı anlama gelmediğini açıklığa kavuşturmalı. Sağ? – Barry

+0

@Barry Doğru. –