2011-04-16 114 views
6

我一直在尋找通過Google C++ style guide,並遇到了這個:在標準名稱空間中聲明名稱的不良做法?

「不要std下宣佈任何事情,標準庫類的甚至不向前聲明std下聲明實體是不確定的行爲,即,不便於攜帶。要從標準庫中聲明實體,請​​包含相應的頭文件。「

有人可以解釋這是什麼意思,爲什麼這是未定義的行爲使用示例代碼?

回答

11

有人可以解釋這是什麼意思,爲什麼這是未定義的行爲使用示例代碼?

下面的程序導致未定義行爲:

namespace std { 
    void foo(int) { } 
} 

#include <iostream> 

int main() { 
    std::cout << "Hello World!" << std::endl; 
} 

爲什麼?它在名稱空間std中聲明名爲foo的函數。至於爲什麼這可能會導致問題,請考慮:標準庫實現可能有其自己的函數,名稱爲foo(),可能由<iostream>中的某個組件使用。您的foo可能會比標準庫實現的foo更好。

+1

除了我們做專門'std :: swap <>()'。我們被允許這樣做。 :p – wilhelmtell 2011-04-16 01:30:26

+0

@wilhelmtell:即使那是非常糟糕的形式。最好在與你的類型相同的命名空間中定義一個交換過載,並讓ADL完成查找它的工作。 – ildjarn 2011-04-16 01:40:10

+4

@wilhelmtell:你可以_specialize_'std'模板;你不能_overload_'std'模板。對於'swap',正如@ildjarn所說,首選解決方案是使用可以通過ADL找到的命名空間範圍函數。 C++ 0x通過添加「可交換」概念給予該技術的正式批准。 – 2011-04-16 01:41:46

6

這是說不要在std命名空間中聲明自己的類型。您可以使用使用標準庫,但您應該通過包含適當的標頭來完成。

基本上,確保你所有的聲明都在你自己的命名空間中,而不是std

4

他們說你應該從這樣的標準庫不向前申報的東西:

// myheader.h 
namespace std{ 
template<class T> 
void SomeStandardFunction(); 
} 

// use std::SomeStandardFunction 

相反,你應該只包括直接頭:

// myheader.h 
#include <SomeHeaderThatContainsSomeStandardFunction> 

// use std::SomeStandardFunction 
+0

缺少空格:template > vector; ( - : – snoofkin 2011-04-16 01:41:33

+0

@soul:更加明顯的問題是在'allocator'之後缺少';',並且'allocator'在被用作模板參數之前需要被完全定義,所以我改變了這個示例:) – Xeo 2011-04-16 01:49:23

2

這並不是說「不要使用標準庫」。

要使用某些東西並聲明某些東西是兩回事。這是說不要聲明任何東西,因爲不要像「class ostream;」那樣做。我想人們以前必須聲明它才能使用它,但現在,因爲事物是在名稱空間std中聲明的,所以只需包含頭文件。

檢查this出。

10

首先,與Google風格指南中的大部分內容一樣,它實際上是錯誤的。該標準特別允許您在命名空間標準中定義幾個特定的​​實體(例如,在用戶定義的類型上對現有模板進行專業化)。

但是,忽略這些例外情況,它們確實有正確的總體思路 - 您的代碼通常屬於其他比命名空間標準。你可以把它放在全局命名空間中,或者你可以定義另一個命名空間,但你應該單獨離開std

你也應該不是嘗試前向聲明標準庫中的任何東西。標準函數允許(例如)包含額外的參數,只要它們包含默認值,這樣就可以用標準方式調用它們。如果你嘗試自己聲明它們,而不是聲明現有的函數,那麼最終可能會聲明一個模糊的超載。

底線:是的,請使用標準庫。當你使用它時,通過包含標準頭文件來獲取聲明,而不是通過編寫自己的頭文件。

+1

+1擊敗我:「它實際上是錯誤的......現有模板的專業化......」。專門研究'std :: swap <>()'是一種常見和可接受的做法。 「 – wilhelmtell 2011-04-16 01:28:52

+4

+1」首先,**像很多Google風格指南**一樣,實際上是錯誤的。「 – ildjarn 2011-04-16 02:29:42

相關問題