2012-01-13 54 views
1

following code的編譯在MSVC++,但在GCC 4.5.1不編譯的聲明中的模板類型規範的一部分:`decltype`作爲模板函數

#include <iostream> 

template< typename PT, bool pB > 
struct TA 
{ 
    PT m; 
    TA(PT fT) : 
    m(fT) 
    { 
    std::cout << "TA<" << pB << ">::TA() : " << m << std::endl; 
    } 
    PT operator()(PT fT) 
    { 
    std::cout << "TA<" << pB << ">::() : " << m << " and " << fT << std::endl; 
    return (m); 
    } 
}; 

template< typename PT > 
PT Foo(PT fT) 
{ 
std::cout << "Foo() : " << fT << std::endl; 
return (fT); 
} 

// Does not compile in GCC 4.5.1, compiles in MSVC++2010. 
// Substitute TA< decltype(fF(std::forward<PP>(fP))), pB > with 
// TA< double, pB > to compile with GCC. 
template< bool pB, typename PF, typename PP > 
auto Func(PF fF, PP && fP, TA< decltype(fF(std::forward<PP>(fP))), pB > && fA) 
-> decltype(fF(std::forward<PP>(fP))) 
{ 
decltype(fF(std::forward<PP>(fP))) lResult(fF(std::forward<PP>(fP))); 

fA(lResult); 

return (lResult); 
} 

int main(void) 
{ 
Func<true>(Foo<double>, -1.2, 2.1); 
return (0); 
} 

註釋點有問題的線路和節目修復(從設計角度來看,這不是一個修復,只是一個編譯修復)。幾個問題:

  1. MSVC++是否正確編譯?

  2. 如果我們在

auto Func(PF fF, PP && fP, TA< decltype(fF(std::forward<PP>(fP))), pB > && fA)

TA< decltype(fF(std::forward<PP>(fP))), pB >更改參數爲了

auto Func(PF fF, TA< decltype(fF(std::forward<PP>(fP))), pB > && fA, PP && fP)

它不會編譯,因爲編譯器將fP爲未聲明的變量。從邏輯上講,編譯器確實需要在這一點上知道fP,無論如何它不會解析整個聲明,因爲它跟蹤返回類型?爲什麼不能「跳過」第二個函數參數,看看fP是否在函數聲明後面聲明?或者我錯過了一些基本的東西(也許是標準中的一些段落)?

回答

1
  1. 我相信MSVC是正確的。

  2. 由於該名稱尚未在範圍內,因此不能在較早的聲明中引用稍後的參數。爲了確定fA參數的類型,fPfF必須在範圍內,以便可以評估decltype表達式。

如果明確指定模板參數然後它用gcc:

Func< true,decltype(&Foo<double>),double>(Foo<double>, -1.2, 2.1); 

這並指定「雙規」直接爲TA工程參數意味着一個事實,即使用相關的輸入TA參數可防止PFPP的類型扣除。我不明白爲什麼會這樣。

+0

我想這是GCC的問題。我習慣GCC在語言結構方面更先進,所以我感到有些驚訝。順便說一下,GCC的「解決方法」很好,但我沒有檢查。 – lapk 2012-01-13 15:34:57