【发布时间】:2010-08-02 13:01:54
【问题描述】:
我正在尝试使用 MSVC 在 Windows 上编译 Flusspferd,但由于模板实例化问题而失败。为了便于解释,我用更简单的术语重写了这个问题:
#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 用于未定义未定义类型但使用其其他构造函数的地方:
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
};
【问题讨论】:
-
这个结构应该实现什么?
标签: c++ visual-c++ templates gcc