2010-08-02 65 views
1

我想在Windows上使用MSVC編譯Flusspferd,但由於模板實例化問題而失敗。爲了便於說明,我重寫了簡單來說這個問題:MSVC:隱式模板實例化,但模板化構造函數未使用

#include <boost/utility/enable_if.hpp> 
#include <boost/type_traits/is_convertible.hpp> 

class UndefinedType; 

class A 
{ 

}; 

class TestClass { 

public: 

    TestClass(A* a) 
    { 

    } 

    template<typename OtherType> 
    TestClass(OtherType t, typename boost::disable_if<typename boost::is_convertible<OtherType, UndefinedType>::type>::type * = 0) 
    { 

    } 
}; 

的問題是,TestClass中包含使用的boost :: is_convertible與轉發類UndefinedType一個模板構造函數。 is_convertible僅適用於完整類型,這意味着此構造函數只應在定義UndefinedType時使用,否則模板實例化將失敗,並顯示C2139。

在Flusspferd的TestClass的是在UndefinedType沒有被定義的地方使用,但使用它的其它構造:

void test() 
{ 
    A* a = new A(); 
    TestClass test(a); // will instantiate the templated constructor, but why? 
} 

雖然TestClass中(A * a)是造成這種情況的最具體的構造,模板將由於is_convertible而被實例化,導致C2139。

GCC編譯得很好,所以問題是:爲什麼不是MSVC?誰是對的?有沒有辦法解決這個問題?

感謝您的幫助!

更新:

MSalters是正確的。正確的行爲是未定義的。從C++標準:

如果重載解析過程可以確定調用的正確函數而無需實例化類模板定義,則不指定實例是否實際發生。

template <class T> struct S { 
    operator int(); 
}; 

void f(int); 
void f(S<int>&); 
void f(S<float>); 

void g(S<int>& sr) { 
    f(sr); // instantiation of S<int> allowed but not required 
      // instantiation of S<float> allowed but not required 
}; 
+0

這個構想應該實現什麼? – 2010-08-02 13:29:30

回答

2

如您所述,「is_convertible只適用於完整類型」。這意味着如果你違反了這個先決條件,任何事情都可能發生 - 特別是未定義的行爲。所以GCC和MSVC都是「正確的」 - 他們既沒有義務產生工作代碼也沒有錯誤。