2010-06-04 73 views
5

今天我的一個朋友告訴我,下面的代碼編譯以及他的Visual Studio 2008:Visual C++編譯器允許從屬名稱作爲沒有「typename」的類型?

#include <vector> 
struct A 
{ 
    static int const const_iterator = 100; 
}; 
int i; 
template <typename T> 
void PrintAll(const T & obj) 
{ 
    T::const_iterator *i; 
} 
int main() 
{ 
    std::vector<int> v; 
    A a; 
    PrintAll(a); 
    PrintAll(v); 
    return 0; 
} 

我通常使用G ++,它總是拒絕通過第二PrintAll()調用。據我所知,對於這個問題,g ++正在做翻譯模板的標準方式。

那麼,我的知識是錯誤的,還是VS2008的擴展?

+0

這是/ Za(嚴格)還是/ Ze(默認,擴展)? – MSalters 2010-06-04 15:23:22

+0

@ MSalters:我剛剛嘗試過/ ZA。沒有看到任何區別... – hpsMouse 2010-06-04 15:56:04

回答

8

這不是一個擴展。

VC++從未付諸實施兩個階段的解釋正確:

  1. 在定義的點,解析模板,並確定所有非依賴的名字
  2. 在實例化點,檢查模板生成有效的代碼

VC++從來沒有實現第一階段......這很不方便,因爲它不僅意味着它接受不符合規範的代碼,而且它在某些情況下會產生完全不同的代碼。

void foo(int) { std::cout << "int" << std::endl; } 

template <class T> void tfoo() { foo(2.0); } 

void foo(double) { std::cout << "double" << std::endl; } 

int main(int argc, char* argv[]) 
{ 
    tfoo<Dummy>(); 
} 

有了這個代碼:

  • 標準的編譯器將打印「INT」,因爲它是可在模板的定義和foo分辨率點的唯一定義不依賴於T
  • VC++將打印「雙」,因爲它從來沒有與第1階段

這似乎愚蠢儘可能的差異去打擾,但如果你仔細想想的數量包括你在一個大的程序,有是一種風險,有人會在你的模板代碼之後引入過載...... BAM:/

+0

有沒有辦法讓'VC++'至少產生一個警告?這種行爲對於必須適用於多個編譯器的代碼來說是令人討厭的。我們團隊的開發人員忘記隨時添加關鍵字,代碼無法在'Clang'上編譯# – Samaursa 2015-02-04 23:37:12

+1

@Samaursa:不幸的是,我不知道。如果你使用的是Clang,你可能會很感興趣知道他們正在開發VC++的嵌入式驅動程序,因此你可以直接從Visual Studio調用Clang。 – 2015-02-05 07:22:36

1

我不確定「擴展」究竟是如何描述VC++在這方面的,但是,gcc在這方面有更好的一致性。

+0

這不是Visual Studio在寬容模式下的行爲嗎?我認爲它會在嚴格模式下拒絕代碼,並實現此擴展以便與VC6向後兼容。 – MSalters 2010-06-04 15:21:51

+0

@ MSalter:不,VC++即使使用/ Za也會接受該代碼。 – 2010-06-04 15:43:43

相關問題