2010-08-16 21 views
5

在試圖回答this question時,我想建議使用enable_if + disable_if以允許基於類型是(或不是)多態的事實來重載方法。enable_if + disable_if組合引發模棱兩可的呼叫

所以我創建了一個小的測試文件:

template <class T> 
void* address_of(T* p, 
       boost::enable_if< boost::is_polymorphic<T> >* dummy = 0) 
{ return dynamic_cast<void*>(p); } 

template <class T> 
void* address_of(T* p, 
       boost::disable_if< boost::is_polymorphic<T> >* dummy = 0) 
{ return static_cast<void*>(p); } 

struct N { int x; }; 


int main(int argc, char* argv[]) 
{ 
    N n; 
    std::cout << address_of(&n) << std::endl; 
    return 0; 
} 

這似乎很溫順。

但是GCC(3.4 ...)這個嗆:

test.cpp: In function int main(int, char**) :
test.cpp:29: error: call of overloaded address_of(N*) is ambiguous
test.cpp:17: note: candidates are: void* address_of(T*, boost::enable_if<boost::is_polymorphic<T>, void>*) [with T = N]
test.cpp:20: note: void* address_of(T*, boost::disable_if<boost::is_polymorphic<T>, void>*) [with T = N]

它似乎很清楚,我的人的心靈,其過載應在此處使用。我的意思是,我似乎很清楚,我已經定義了一個替代方案,並且一次只能使用一個功能......並且我會認爲SFINAE會照顧無用的過載。

我使用...(省略號)代替disable_if並且需要一個虛擬的第二個參數來修補它,但是我仍然對編譯器爲什麼會窒息這個問題感興趣。

回答

11

編譯器嗆,因爲你enable_ifdisable_if忘記尾隨::type。模板總是被定義的;當且僅當表達式爲true(對於enable_if)或false(對於disable_if),成員type才存在。

template <class T> 
void* address_of(T* p, 
       typename boost::enable_if< boost::is_polymorphic<T> >::type* dummy = 0) 
{ return dynamic_cast<void*>(p); } 

template <class T> 
void* address_of(T* p, 
       typename boost::disable_if< boost::is_polymorphic<T> >::type* dummy = 0) 
{ return static_cast<void*>(p); } 

沒有尾隨::type,你的函數模板只是創建佔據指針的enable_ifdisable_if作爲第二個參數的實例重載。尾隨::type,模板或者使用void*類型的第二個參數創建過載,或者刪除過載(即期望的行爲)。

+0

該死!我知道它應該工作... – 2010-08-16 12:02:55

0

使用enable_if的 「返回類型」 的版本工作在3.4.4:gcc version 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)

#include <boost/utility/enable_if.hpp> 
#include <boost/type_traits/is_polymorphic.hpp> 
#include <iostream> 

template <class T> 
typename boost::enable_if< boost::is_polymorphic<T>, void* >::type 
address_of(T* p) 
{ return dynamic_cast<void*>(p); } 

template <class T> 
typename boost::disable_if< boost::is_polymorphic<T>, void* >::type 
address_of(T* p) 
{ return static_cast<void*>(p); } 

struct N { int x; }; 


int main(int argc, char* argv[]) 
{ 
    N n; 
    std::cout << address_of(&n) << std::endl; 
    return 0; 
}