2010-08-02 63 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都是“正确的” - 他们既没有义务产生工作代码也没有错误。