【问题标题】:MSVC: explicit template instantiation fails while implicit instantiation succeedsMSVC:显式模板实例化失败,而隐式实例化成功
【发布时间】: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 错误。 (我认为不需要诊断就不是病态的)。
  • MSVC12 不支持 C++14(或根本不支持)。
  • @JonathanMee 例如我们希望在二进制库中进行此实例化,以便其他代码无需实例化即可调用它。
  • @Jonathan:什么 n.m.说,或者只是为了确保当我在几周(或几个月)后使用该库函数时它会编译。

标签: c++ visual-c++


【解决方案1】:

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

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

  template void helper( int& );
}

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

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

【讨论】:

    猜你喜欢
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多