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

Specifying only some template parameters at call time

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

#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)

但是,当我尝试使用 Intel 的编译器(版本 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);

不过,我想了解为什么原始代码在所有 C++ 14 编译器上都没有给出相同的结果。这是预期编译的东西 successfully/unsuccessfully,还是某种未定义的行为,为什么?

作为参考,这些是我用来编译的命令(在 Linux、各种 versions/flavors 上):

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(不编译您的代码)正确推导 Idcs 而没有 enable_ifhttps://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
}