2011-06-18 78 views
0

又一個模板問題!我試圖得到一個模板方法,如果它對於運營商< <有過載,將會輸出一個對象。 我幾乎所有的工作,並實施了一個enable_if爲了使g ++爲每種類型的對象選擇預期的專業化。模板專精不明確

事情是,與一個非重載的對象,它工作得很好。但是如果超載,我的兩個專業化都是g ++的合理選擇,而不是編譯它會輸出一個模糊的過載錯誤。

下面的代碼:

template<typename T> 
    static void Print(Stream& out, T& param, typename enable_if<CanPrint<T>::value>::type = 0) 
    { 
    out << param; 
    } 

    template<typename T> 
    static void Print(Stream& out, T& param) 
    { 
    out << "/!\\" << typeid(param).name() << " does not have any overload for <<.\n"; 
    } 

我明白爲什麼這樣的事情是不明確的。然而,我想不出一種更明顯的方式......我如何讓編譯器明白第二個重載只能在第一個重載不能被選擇時才被選擇?

回答

1

歧義是因爲默認的參數值。

調用Print(stream, whatever)可以解析爲具有默認第三參數的第一個版本或不具有第三個參數的第二個版本。

刪除默認值,編譯器會理解。否則,他們都可以一直選擇。

+0

是的,但這是事實上。我如何使它工作? –

1

我相信這與模板無關。以這種方式重載的自由函數會帶來相同的錯誤。

檢查這個簡單的代碼示例,它類似於你在做你的模板例如什麼:

void doSomething(int i, int j, int k); 
void doSomething(int i, int j, int k = 10); 


void doSomething(int i, int j, int k) 
{ 

} 

void doSomething(int i, int j) 
{ 

} 


int main() 
{ 
    doSomething(10,20); 
    return 0; 
} 

的錯誤是:

prog.cpp:18: error: call of overloaded ‘doSomething(int, int)’ is ambiguous 
prog.cpp:5: note: candidates are: void doSomething(int, int, int) 
prog.cpp:10: note:     void doSomething(int, int) 

顯然,你不能重載函數這種方式只是基於默認參數。

+0

我確實知道。真正的問題是:如何讓SFINAE在這裏適用? –

+0

@ The-Snake:恕我直言,我不認爲可以。 –

+0

用'enable_if' /'disable_if'你可以。 – Node

8

因爲在這兩種情況下,你有一個函數,它接受一個流,然後你T類型作爲前兩個參數你會得到不確定性。這工作雖然:

#include <iostream> 
#include <boost/utility/enable_if.hpp> 
#include <typeinfo> 

template <class T> 
struct CanPrint { enum { value = 0 }; }; 

template <> 
struct CanPrint<int> { enum { value = 1 }; }; 

template<typename T> 
typename boost::enable_if<CanPrint<T>, void>::type 
    Print(std::ostream& out, T& param) 
{ 
    out << param << std::endl; 
} 

template<typename T> 
typename boost::disable_if<CanPrint<T>, void>::type 
    Print(std::ostream& out, T& param) 
{ 
    out << "/!\\" << typeid(param).name() << " does not have any overload for <<.\n"; 
} 

int main() 
{ 
    int i = 1; 
    double d = 2; 

    Print(std::cout, i); 
    Print(std::cout, d); 
} 
+0

哇o_O!多麼愚蠢,我甚至沒有想過使用返回值!它起作用膨脹,謝謝! –

+0

我的+1,很好的答案。 –

+2

@ The-Snake真正的解決方法是使用'disable_if'去除過載集合中的'錯誤'超載。 –