2012-01-25 78 views
1

我想實現三個功能,有很多錯誤都具有相同簽名:C++模板參數不明確

error C2782: 'T0 ColorBurn(T0,T0)' : template parameter 'T0' is ambiguous 
error C2782: 'T1 ColorDodge(T1,T1)' : template parameter 'T1' is ambiguous 

在那裏我有犯了一個錯誤?
這是我的代碼:

template <class T0> 
T0 ColorBurn(T0 base, T0 blend) 
{ 
    return (blend == 0.0) ? blend : std::max((1.0 - ((1.0 - base)/blend)), 0.0); 
} 
template <class T1> 
T1 ColorDodge(T1 base, T1 blend) 
{ 
    return (blend == 1.0) ? blend : std::min(base/(1.0 - blend), 1.0); 
} 
template <class T> 
T BlendVividLightf(T base, T blend) 
{ 
    return (blend < 0.5) ? ColorBurn(base, (2.0 * blend)) : ColorDodge(base, (2.0 * (blend - 0.5))); 
} 

調用BlendVividLightf的樣本:

static pixel_t blend_vivid_light(pixel_t _p1, pixel_t _p2) 
{ 
    pixel_t po; 
    po.r = BlendVividLightf(_p1.r, _p2.r); 
.... 
} 
pixel_t - is my struct for rgb values: 
typedef struct 
{ 
    float r; 
    float g; 
    float b; 
} pixel_t; 
+1

什麼類型爲T在BlendVividLightf。請顯示該功能的呼叫。 – hansmaad

+0

我已更新我的問題 –

+0

'_p1.r'和'_p2.r'類型爲'double'?如果不是,那麼會導致編譯錯誤。 – iammilind

回答

1

我可以猜到,這個問題是由於floatdouble不匹配。您正在(強制)所有3個函數中的template相同類型參數T0/T1/T。所以當你使用float調用這個函數的時候會有問題。請參閱demo

這可以通過使您的pixel_t成員爲double而不是float來解決。

9

的問題是,當你調用ColorBurnColorDodge的模板參數之一是float,另一個是一個雙:

ColorBurn(base, (2.0 * blend)) 

這裏,base是一個浮點數,表達式2.0 * blend是一個雙精度(因爲2.0是一個雙常數,所以整個表達式變成雙精度)。

現在,編譯器無法決定是否實例化ColorBurn浮點或雙精度。

爲了解決這個問題,改變你的常量轉換爲單精度浮點常量(這很可能是你想要什麼反正):

ColorBurn(base, (2.0f * blend)) 

,類似的還有ColorDodge

請注意,如果您嘗試爲float以外的其他內容實例化BlendVividLightf,您仍然遇到問題 - 您的函數假設處理浮點值的方式過多,因此您必須介紹某些類型轉換如果您希望它們爲其他參數類型工作。

+1

解決方案是使用'static_cast (2.0)'。或者使用命名常量:'static T const doubler = 2.0;'。無論哪種方式,你都強迫常量具有所需的類型。 –

+0

@James:或者,作爲一個小調整,'static_cast (2)'(強調這隻適用於積分常數) –

+0

如果我正確理解他的代碼,它將只適用於浮點類型。 –

2

也許你要投(2.0 *混合),以「T」的結果,並把它傳遞給ColorBurn ... 例如:

ColorBurn(base, static_cast<T>(2.0 * blend)); 
+0

這實際上是非常好的建議! – bronekk

3

問題的原因是0.5double -literal,和T0是一個浮點數。所以你傳遞模板的兩個參數的類型不同,因此編譯器無法決定使用哪一個參數。有兩種解決方案:

  1. 變化0.50.5f,使之成爲float -literal。
  2. 提供明確的類型參數到您的模板,像這樣:

    ColorBurn<float>(base, (2.0 * blend)) 
    
+0

+1因爲這確實是最可靠和最簡單的解決方案。 –

1

您的問題是在這條線:

ColorBurn(base, (2.0 * blend)) ... 

這裏字面2.0將迫使第二個參數轉換爲double,但是由於第一個參數是原來的模板類型,並在後面的代碼在這float中,編譯器無法推斷出您是否打算調用ColorBurn<double>ColorBurn<float>(同樣適用於在此行後面調用ColorDodge)。

您可以通過的修復錯誤:

  • 告訴編譯器顯式模板參數的函數調用
  • 驅動力轉換到太例如翻番的第一個參數... * 1.0
  • 將第二個參數中的雙重文字改爲float literals ... * 2.0f
  • 寫入專業化,或單獨的過載,爲浮點和雙精度和製造上文適當的修改,以確保這兩個參數是相同類型