2011-10-20 17 views
2

如果我有一個模板基類與模板方法:enable_if:一個模板庫的模板化方法的情況下繼承幾次

template <typename T> 
class S 
{ 
public: 

    template <typename U> 
    void f(U p, typename enable_if<is_same<T, U> >::type*dummy = 0) 
    { 
     std::cout << p << std::endl; 
    } 
}; 

對於例如,我簡化方法:它必須僅「存在」如果T ==ü

如果A是這個類:

class A : public S<int> {}; 

然後,我有我想要的東西:

int i = 1; 
A a; 
a.f(i); 

編譯,但

double d = 2.0; 
a.f(d); 

不會編譯:錯誤:調用「A :: F(雙&)」 這是預期的行爲沒有匹配的功能。

,現在讓我們從S<double>也是一個繼承:

class A : public S<int>, public S<double> {}; 

然後將以下代碼不能編譯:

int i = 1; 
A a; 
a.f(i); 
error: request for member ‘f’ is ambiguous 

error: candidates are: template<class U> void S::f(U, typename 
boost::enable_if<boost::is_same<T, U>, void>::type*) [with U = U, T = 
double] 

error:     template<class U> void S::f(U, typename 
boost::enable_if<boost::is_same<T, U>, void>::type*) [with U = U, T = 
int] 

我希望沒有歧義:f<int>只存在S<int>

在編譯器錯誤中,我們可以注意到當這段代碼被編譯時T是已知的,但不是U(U = U)。

任何解釋或「解決方法」?

+2

爲什麼'f'必須被模板化? – Xeo

+0

建立在@ Xeo的評論上:既然你希望'f'的參數是'T',爲什麼不直接說'enable_if'呢?'template struct S {void f(T p){std :: cout << p << std :: endl; }};' –

+0

(我剛剛重讀了你的問題,看到你說的方法被簡化了,所以也許你的實際代碼真的需要'f'作爲方法模板)。 –

回答

4

嘗試這種情況:

a.S<int>::f(i); 

...或可替代地注入功能分爲A,例如

class A : public S<int>, public S<double> 
{ 
public: 
    using S<int>::f; 
    using S<double>::f; 
}; 
+0

想要發佈替代版本,該死的編輯! :P – Xeo

0

你是對的它只存在於S中,但是兩次。每種類型一次,int和double。所以在你的情況下,你需要指定你想要調用的函數。 Nim的解決方案就像那樣。

+0

「*你是對的,它只存在於S中,但是存在兩次。*」實際上情況是有兩個不同的'S's。 – ildjarn

0

別人給予很好的解決方法,但我想回答你有

I expected there is no ambiguity : f<int> exists only for S<int> .

你說a.f(i)所以它首先需要查找名稱fA其他問題。它找到兩個f s。在S<int>S<double>。在名稱查詢時,它還不知道它以後可能只選擇S<int>::f作爲贏家,因爲S<double>::f將被SFINAE扔掉。名稱查找和重載解析以及模板參數演繹的清晰分離不允許這種混合。