MSVC:隐式模板实例化,但不使用模板化构造函数 [英] MSVC: Implicit Template Instantiation, though templated constructor not used

查看:240
本文介绍了MSVC:隐式模板实例化,但不使用模板化构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在Windows上使用MSVC编译 Flusspferd ,但由于模板实例化问题而失败。为了便于解释,我用简单的语句重写了这个问题:

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

class UndefinedType;

class A
{

};

class TestClass {

public:

TestClass(A * a)
{

}

模板< 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); //会实例化模板化的构造函数,但是为什么?



$ b $ p
$ b

尽管TestClass(A * a)是这种情况下最具体的构造函数,由于is_convertible,模板将被实例化导致C2139。



GCC编译得很好,所以问题是:为什么不是MSVC?谁是对的?有没有办法解决这个问题?



感谢您的帮助!



更新:



MSalters是正确的。正确的行为是未定义的。从C ++标准:

如果重载解析过程可以确定调用正确的函数而不实例化类模板定义,则不确定实例是否实际发生。

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

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

void g(S< int>& sr){
f(sr); //实例化S< int>允许但不是必需的
// S< float>的实例化允许但不要求
};


解决方案

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


I am trying to compile Flusspferd on Windows using MSVC, but it fails due to a template instantiation problem. For the ease of explanation I rewrote the problem in simpler terms:

#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)
    {

    }
};

The problem is, that TestClass contains a templated constructor that uses boost::is_convertible with the forwarded class UndefinedType. is_convertible only works for complete types, meaning that this constructor should only be used when UndefinedType has been defined, otherwise the template instantiation will fail with C2139.

In Flusspferd the TestClass is used in places where UndefinedType has not been defined, but using its other constructor:

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

Though TestClass(A* a) is the most specific constructor for this situation, the template will be instantiated leading to C2139 because of is_convertible.

GCC compiles fine, so the question is: why isn't MSVC? Who is right? Is there a way to get around this?

Thanks for the help!

Update:

MSalters is right. The correct behaviour is undefined. From the C++-Standard:

If the overload resolution process can determine the correct function to call without instantiating a class template definition, it is unspecified whether that instantiation actually takes place.

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
};

解决方案

As you state, "is_convertible only works for complete types". This means that if you violate this precondition, anything can happen - in particular undefined behavior. So both GCC and MSVC are "right" - they're neither obliged to produce working code nor an error.

这篇关于MSVC:隐式模板实例化,但不使用模板化构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆