MSVC:显式模板实例化失败,而隐式实例化成功

Posted

技术标签:

【中文标题】MSVC:显式模板实例化失败,而隐式实例化成功【英文标题】:MSVC: explicit template instantiation fails while implicit instantiation succeeds 【发布时间】:2016-08-15 09:21:10 【问题描述】:

我刚刚遇到了 MSVC(版本 12 更新 5)的问题:

如果模板函数具有通过 SFINAE 禁用的重载,则显式实例化模板函数会失败。但是,调用该函数(从而隐式实例化它)是可行的。

示例代码:

#include <type_traits>

template <typename T>
std::enable_if_t< std::is_integral<T>::value,  // test is true for T=int
void> foo( T& ) 

template <typename T>
std::enable_if_t< std::is_pointer<T>::value,  // test is false for T=int
void> foo( T& ) 

void bar( )

  int i;
  foo( i );  // calls foo( int& ) (obviously), compiles fine

template void foo( int& );  // explicit instantiation, throws compiler error

我得到的编译器错误是error C2794: 'type' : is not a member of any direct or indirect base class of 'std::enable_if&lt;false,void&gt;'。 GCC 似乎可以使用相同的代码(除了缺少 main 函数):live on Ideone。

这是一个 MSVC 错误吗?有没有一种好方法可以使这些显式模板实例化?

【问题讨论】:

gcc/clang 都接受它,我会说这是一个 MSVC 错误。 (我认为不需要诊断就不是病态的)。 在线编译webcompiler.cloudapp.net。在rextester.com/l/cpp_online_compiler_visual MSVC12 不支持 C++14(或根本不支持)。 @JonathanMee 例如我们希望在二进制库中进行此实例化,以便其他代码无需实例化即可调用它。 @Jonathan:什么 n.m.说,或者只是为了确保当我在几周(或几个月)后使用该库函数时它会编译。 【参考方案1】:

以下允许实例化函数,确保它可以编译并且应该(根据我的理解)也将它放入 .obj 文件中:

namespace 
  template <typename T>
  void helper( T& A )
  
    foo( A );
  

  template void helper( int& );

这里的诀窍是,helper(..) 既不是重载,也不是任何类型的禁用。对禁用的重载进行排序会延迟到对helper(..) 内的foo(..) 的“调用”,MSVC 成功解决了这个问题。

编辑: 正如我们所看到的,其他编译器理解我的原始代码以及更新版本的 MSVC(感谢 Niall),我认为这是我的 MSVC 版本的错误,并考虑充分考虑这部分问题。

【讨论】:

以上是关于MSVC:显式模板实例化失败,而隐式实例化成功的主要内容,如果未能解决你的问题,请参考以下文章

使用模板化成员函数显式实例化模板类

如何对复杂的模板化函数进行显式实例化?和相关的 Intellisense 错误

显式实例化模板类的显式实例化模板方法

C++初识模板

如何防止特定模板的隐式模板实例化?

C++初阶模板