2012-12-19 47 views
10

聲明符。是的,宣言者。他們是很多編碼公約辯論的來源。這是一個很好的爭論話題 - C++不會規定哪一個比另一個更好(它不關心!)。因此,我們可以寫這些,而不必擔心有人會取笑你:可變參數模板中的聲明符修飾符位置

int x; 

int& a = x; 
int &b = x; 

int* c = &x; 
int *d = &x; 

在語法方面,bd比其他「更有效」。我們被要求在名稱前加上說明修飾語:

int m, *n; // m is an int; n is a pointer to int 

但是這個潮流似乎轉而支持一個。用C++ 11的可變參數模板,說明符的位置似乎僅限於其中改性劑是靠近基體類型形式:

template<typename... Ts> 
void VariadicFuncRef(const Ts&... args) { } 
          ^
template<typename... Ts> 
void VariadicFuncPtr(Ts*... args) { } 
        ^

它是寫這些形式的錯誤:

template<typename... Ts> 
void VariadicFuncRef(const Ts... &args) { } 

template<typename... Ts> 
void VariadicFuncPtr(Ts... *args) { } 

有關具體示例,請點擊here

所以,我的問題是這樣的: 爲什麼我們只限於這種(合法)形式,不能使用其他?

任何想法傢伙?

其他1:我也對這個「規則」爲什麼是「強制執行」的設計決定感興趣。

+0

+1。順便說一句,好問題。 – Nawaz

+0

@Nawaz我花了幾分鐘時間試圖用錯誤的語法編譯代碼。獲得的經驗:不要使用您不熟悉的功能。 –

+0

這將恢復你的世界:這三個......也是宣言者的一部分! –

回答

3

首先,我不會說int &a更有效int& a。你可能會說它更具可讀性,或者說是一種很好的做法,但這完全是另一回事。

其次,參數解包語法T...可以讀作「上的...左側的類型圖案擴大,形成相同或不同的實際功能的參數類型相匹配的型圖案的形式」。所以當你寫f(T&...)時,它可以擴展到f(int&, float&, double&, Xyz&, Abc&)。但是,當語法爲T...&時,這似乎並不明顯(至少對我而言)。所以也許,這是其中幾個可能的之一,爲什麼標準這樣做。

另請注意,argsT&...args可選。所以如果你不寫,那麼void f(T...&)看起來很奇怪(至少對我來說),void f(T&...)至少在美學上看起來更好。

您還可以比較語法,如:T * const & ...T... * const &類型模式在前者的語法中比在後者中更明顯。

+0

好點。唉,我們也可以說'T ...&arg'中的&args'(如果這是有效的)擴展爲像'int&,float&...'。 –

+0

哈哈哈!代碼美學! –

+1

我有點相信你的答案。非常感謝。但我也可以使用第三方的意見。我希望你能等得起。 –

4

舊的聲明語法只是一個無關緊要的空白的規則,但你的想法是兩個。我懷疑委員會是否贊成有足夠的兩條規則。

把聲明符左邊的選擇很可能是基於以下兩個原因:

  • 地道的C++時下喜歡int* x而非int *x(Bjarne的使用前者爲例子)。大多數人認爲聲明語法是一個錯誤。
  • 參數包擴展將東西擴展到...的左側,而不是右側。
+0

請您詳細說明您的第二點? –

+0

@MarkGarcia'std :: forward (args)...,args'正在擴展包的左邊'...',而不是右邊。 – Pubby

+0

好的。這完全是我的聯盟('std :: forward')。但我在學習! (不需要詳細說明'std :: forward') –

2

達到了完美,而不是當沒有更多東西需要補充時,而是什麼也沒有剩下要拿走的時候。

- 安東尼·德·聖艾修伯裏

在編程語言設計難度,不增加新的功能,它是把它們添加到避免。每一個功能,語法的每一個變化,是有代價的:

  • 他們必須在編譯器進行特定的編碼
  • 它們對引入錯誤的風險
  • 它們帶來另一個特性交互不良的風險/變化
  • ...

在C和C++的語法(大部分)空格不敏感,因此它不會不管你在哪裏放置&*兩種偏好都可以共存而無額外負擔;然而,在可變模板的情況下,由於...令牌的緣故,它確實很重要。委員會因此決定選擇一個,他們選擇了C++中最常用的語言(強調全部類型而不是基本類型)。