2016-11-20 46 views
3

考慮下面的小例子:不是最後一個模板參數的扣減和參數包是這個有效的代碼嗎?

template<typename... A, typename R> 
void f(A&&..., R(*)(A...)) {} 

void g(int, char) {} 

int main() { 
    f<int, char>(42, 'c', g); 
} 

的參數包A不是最後一個參數。
無論如何,我認爲R可能已經從函數指針推導出來,因爲[temp.param]/11

GCC(6.2)本agrees with me,而鐺(3.9)rejects the code,並說,它不能推斷出模板參數R

我的期望是否錯誤,因此GCC不應該接受它,或者是鏗鏘聲的問題?

+0

當原型是'R(*)(A ...),A && ...'時會發生什麼?我認爲'clang'是正確的,因爲參數包應該吞下函數指針,因此不能推導出'R'。 – StoryTeller

+0

@StoryTeller好點。兩個編譯器都接受這些代碼。無論如何,這是不完全一樣的。移動函數指針允許我也刪除''並將'f'作爲f(g,42,'c')'調用。 – skypjack

+0

我不確定*它是一個問題。可能只是一個GCC增強。 – StoryTeller

回答

1

從這提到的段落:

如果一個類模板,模板變量或別名模板的模板參數具有默認模板參數,以後每次模板參數應要麼有一個默認的模板 - 參數提供或作爲模板參數包。如果主類模板,主變量模板或別名模板的模板參數是模板參數包,則它應該是最後一個模板參數。 除非可以從函數模板的參數類型列表([dcl.fct])推導出模板參數,否則函數模板的模板參數包不應跟隨其他模板參數,或者具有默認參數([temp.deduct])沒有默認參數的扣減指南模板([temp.deduct.guide])的模板參數可以從扣減指南模板的參數類型列表中推導出來。 [實施例:

template<class T1 = int, class T2> class B; // error 

// U can be neither deduced from the parameter-type-list nor specified 
template<class... T, class... U> void f() { } // error 
template<class... T, class U> void g() { } // error 

- 端示例]

在這種情況下,template<typename... A, typename R>不能從功能模板的參數類型列表推導出因爲:

void f(A&&..., R(*)(A...)) 

A&&...是貪婪的,它會消耗g作爲A&&而不是R(*)(A...)

說到迂腐,如在temp.deduct.call-1

對於發生在參數聲明列表,扣除用於呼叫的每個剩餘參數進行的端部的函數參數包,取的在P型函數參數包的declarator-id作爲相應的函數模板參數類型。每個推導都推導模板參數,以便在由函數參數包擴展的模板參數包中隨後的位置。 當函數參數包出現在未推導的上下文中時([temp.deduct.type]),該參數包的類型永遠不會被推斷出來。

並且如在temp.deduct.type#9

如果P具有包含< T A形式>或< I>,則P的相應模板參數列表的每個參數Pi的與相應的比較A的相應模板參數列表的參數Ai。如果P的模板參數列表包含不是最後一個模板參數的包擴展,則整個模板參數列表是非推導的上下文。如果Pi爲一包的擴展,那麼Pi的圖案與A.

的模板參數列表中的每個其餘參數相比,它不能被指定爲可以在第三個例子中看到。

鏘當拒絕它是正確的。

+1

是不是關於類模板的最後一個片段,而不是函數模板?我正在從手機閱讀它,我有一些困難,正確的,對不起。 – skypjack

+0

'14.8.2.5從類型[temp.deduct.type]中推導模板參數'是'14.8函數模板特殊化[temp.fct.spec]' – Danh

+0

的一部分無論如何,我添加了一些來自[temp.deduct.call] – Danh

相關問題