注意:这个问题是关于显式实例化,而不是显式特化。
请看以下示例:
template <bool A, typename X>
void f (X &x) {} // 1
template <bool A>
void f (int &x) {} // 2
template void f<true> (int &x); // 3
假设我最初的目标是仅显式实例化第二个函数模板,A = true
因此我编写了 line // 3
。然而直观地,第一个定义也可以用 line 显式实例化,// 3
这有点问题,因为我实际上无法用当前语法转义它,因为bool A
在我的情况下无法推断。从理论上讲,如果两个函数模板最终都被显式实例化,我什至不介意,但最有趣的部分是实际的编译结果。
(在所有编译成功的情况下,只有第二个函数模板被实例化。)
原案。
msvc
用和编译clang
。编译失败gcc
:错误:'void f(int&)' 的模版特化 'f' 模棱两可
在第一个函数模板中替换
bool A
为bool A = true
使 gcc 编译它。替换
X &x
为X &&x
(forwarding reference) 会使 clang 无法编译它:错误:“f”的显式实例化的部分排序不明确
这是最激烈案例的演示。
(使用了 Godbolt 上可用的编译器的最新版本)
所以我的问题是——这种情况下的显式实例化行为是否真的被指定得如此微弱,以至于很容易进入这种雷区,或者可能msvc
是最符合标准的?就个人而言,我不觉得我最初的目标是超凡脱俗,即使与当前的语法有点冲突。