c++ - MSVC : Implicit Template Instantiation, 虽然未使用模板化构造函数

标签 c++ visual-c++ templates gcc

我正在尝试编译 Flusspferd在 Windows 上使用 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 包含一个模板构造函数,该构造函数使用带有转发类 UndefinedType 的 boost::is_convertible。 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
};

最佳答案

正如您所说,“is_convertible 仅适用于完整类型”。这意味着如果你违反了这个先决条件,任何事情都可能发生——尤其是未定义的行为。所以 GCC 和 MSVC 都是“正确的”——它们既没有义务生成工作代码也没有错误。

关于c++ - MSVC : Implicit Template Instantiation, 虽然未使用模板化构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3387991/

相关文章:

c++ - 另一个链接器问题

c++ - Vector 与 List 的真实世界示例显示了每个比另一个更有效的场景

c++ - 返回 C++ 函数最后一个参数的通用包装器

c++ - 将成员函数指针作为参数传递给模板方法

c++ - 自动编写 MCVE(重现错误的最小源代码)?

内部类中的 C++ 模板运算符重载

c++ - int(int, int) 样式模板函数类型语法

C++ cin 在 while 循环中使用,但控制台屏幕未保持

c++ - 具有对齐成员的对象的动态分配 - 可能的解决方案?

C++:从模板参数继承