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<false,void>'
。
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:显式模板实例化失败,而隐式实例化成功的主要内容,如果未能解决你的问题,请参考以下文章