在调用时仅指定一些模板参数

Specifying only some template parameters at call time

本文关键字:参数 调用      更新时间:2023-10-16

考虑一小段可变参数模板代码:

#include <type_traits>
template<int Dim, class... Idcs>
std::enable_if_t<sizeof...(Idcs) == 1> doit(Idcs... idcs)
{}
int main()
{
doit<0>(1);
}

当我使用 GCC/Clang 编译它时,编译得很好,Idcs被推导出为(int)

但是,当我尝试使用英特尔的编译器(版本 18.0.0,20170811)编译它时,出于某种原因,它认为我手动将Idcs指定为空参数包,然后enable_if_t失败。

来自 icc 的编译器错误:

myfile.cpp(9): error: no instance of function template "doit" matches the argument list
argument types are: (int)
doit<0>(1);
^
myfile.cpp(4): note: this candidate was rejected because there is a type mismatch after argument substitution
std::enable_if_t<sizeof...(Idcs) == 1> doit(Idcs... idcs)
^
compilation aborted for myfile.cpp (code 2)

可以通过更改main()内部的调用以完全指定所有模板参数来解决此问题

doit<0, int>(1);

但是,我想了解为什么原始代码在所有 14 个编译器上没有给出相同的结果C++。这是期望成功/失败编译的东西,还是某种未定义的行为,为什么?

作为参考,这些是我用来编译的命令(在 Linux 上,各种版本/风格):

g++ -std=c++14 myfile.cpp
clang++ -std=c++14 myfile.cpp
icc -std=c++14 myfile.cpp

这很可能是 icc 中的一个错误,在 v19 中修复了:https://godbolt.org/z/k1vbY9

更多的研究表明,icc v18(不编译你的代码)在没有enable_if的情况下正确推断Idcshttps://godbolt.org/z/WCZ_w8:

template<size_t Dim, class... Idcs>
size_t doit(Idcs... idcs)
{
static_assert(sizeof...(Idcs) == 1);
return sizeof... (Idcs);
}
auto test()
{
return doit<0>(1); // correctly returns 1 even on icc v18
}