2010-03-19 13 views
8

neden aşağıdaki vermek hiçbir derleme hatası ?: sadece sessizce derleyici tarafından göz ardı edilir sankiSınıf şablon üyesi işlevi için "varsayılan parametre hatasının yeniden tanımlanması" yok mu?

// T.h 

template<class T> class X 
{ 
public: 
    void foo(int a = 42); 
}; 

// Main.cpp 

#include "T.h" 
#include <iostream> 

template<class T> void X<T>::foo(int a = 13) 
{ 
    std::cout << a << std::endl; 
} 

int main() 
{ 
    X<int> x; 
    x.foo(); // prints 42 
} 

görünüyor. Bu neden?
Sınıf şablonu tanımı, bir başlık dosyası yerine Main.cpp içeriyorsa, gerçekten varsayılan parametre hatasını yeniden tanımlıyorum.

Artık derleyici, sıradan (şablonsuz) bir işlev olsaydı bu konuda şikayette bulunacağını biliyorum.

Sınıf şablonu üye işlevlerinde veya işlev şablonlarında standart varsayılan parametreler hakkında ne söylemelidir? 8.3.6 §6 sınıfında üye işlev bildiriminde tarafından sağlanan varsayılan argümanlar kümesine eklenir sınıf tanımının dışında görünen üye işlev tanımında varsayılan argümanlar

+1

g ++ * * bir derleme ile derlemeyi iptal eder. – sth

+0

"... şablon bildirimi içeriyorsa ..." derken, sınıf şablonu tanımını yani 'şablon sınıf x {....}; Öyleyse, bu şablon sınıfı tanımıyla include yönergesini değiştirmenin farklı bir derleyici mesajı oluşturduğunu mu söylüyorsunuz? Bu, başlık dosyasında başka bir şey olduğunu gösterir, yani başlık dosyasının tüm içeriklerini içerme yönergesinin olduğu yere kopyalamayı deneyin ve muhtemelen derleyici uyarısı almazsınız? – Troubadour

+0

Bir şekilde bu VC++ hatası ile ilgili olabilir: https://connect.microsoft.com/VisualStudio/feedback/details/496593/msdn-forum-splitting-templated-function-with-default-argument-into-declaration-definition -gives-derleme hatası –

cevap

3

tanım.
[Örnek:

class C { 
    void f(int i = 3); 
    void g(int i, int j = 99); 
}; 
void C::f(int i = 3) // error: default argument already 
{ }     // specified in class scope 
void C::g(int i = 88, int j) // in this translation unit, 
{ }       // C::g can be called with no argument 

--end Örnek]

standardına göre, hatayla vermelidir.

+3

@tusbar, yalnızca bu paragrafın bir bölümünü alıntılıyorsunuz. Bunun başında "Sınıf şablonlarının üye işlevleri hariç ..." yazıyor. –

+4

İlginç: C++ 03, C++ 98'den farklıdır. C++ 03, C++ 98 metninden alıntıdır. C++ 03, sınıf şablonlarının istisnasını ekler ve paragrafa eklenir. "Bir sınıf şablonunun bir üye işlevi için varsayılan argümanlar, üye işlevinin ilk bildirgesinde belirtilir. sınıf şablonunda. " - Bunun, sınıf dışı üyelerin sınıf dışı tanımlarında varsayılan argümanları sınıfta [varsayılan olarak sınıfın dışına değil] belirtilmesi gerektiğini söyleyerek söylemem gerektiğini düşünüyorum. belirsiz (çiftleri yasaklıyor mu?). –

+1

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects adresine baktım.html # 217 ve niyet, şablon üyeleri için sınıf dışı varsayılan arşivleri yasaklamak gibi görünüyor. Ayrıca, artık sınıf dışı varsayılan argümanı sınıf içinde birinden ayrı olarak kabul edildiğinden, sözcüksel olarak aynı olsa bile, "ilk deklarasyonda" kısıtını "ihlal edecek" olduğunu düşünüyorum. Yani derleme zamanı hatası alırsanız bu mantıklıdır. "3.13 numaralı" John Spicer, bu belgede okunabilir anlamına gelir: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1995/N0607.pdf –

İlgili konular