模板参数包引发错误,而显式参数不是

Template parameter pack provokes error while explicit parameters not

本文关键字:参数 包引发 错误      更新时间:2023-10-16

以下代码(实时演示)在clang/gcc上运行良好,但在icc和msvc上编译失败。

唯一的区别是在class A中使用了模板参数包,而class B明确地给出了所有模板参数。

正确的行为是什么?代码不正确吗?我是不是错过了什么?还是仅仅因为msvc/icc不符合标准?

更新

测试的编译器版本:

作品:

  • gcc 4.7.3、4.8.1、4.8.2、4.9.0、4.9.2
  • clang 3.3、3.4.13.5.0、3.5.1、3.6.0rc2

不起作用:

  • msvc-12.0(2013)更新4
  • icc-13.0.1

代码

#include <unordered_map>
template <class Container>
struct A
{};
// the following won't compile on some compilers (msvc, icc)
template <class... Args>              // line 8
struct A<std::unordered_map<Args...>> // line 9
{
};
template <class Container>
struct B
{};
// the following compiles fine
template <class K, class T, class H, class P, class A>
struct B<std::unordered_map<K, T, H, P, A>>
{
};
int main(void)
{
    typedef std::unordered_map<int, int> my_map;
    A<my_map> a;
    B<my_map> b;
    return 0;
}

icc错误

test-parameter-pack.cpp(9): error: too few arguments for class template "std::unordered_map"
struct A<std::unordered_map<Args...>>
^
test-parameter-pack.cpp(8): warning #885: template parameter "Args" is not used in or cannot be deduced from the template argument list of class template "A<<error-type>>"
template <class... Args>
^

msvc-12.0更新4出错

test-parameter-pack.cpp
test-parameter-pack.cpp(9) : error C2976: 'std::unordered_map' : too few template arguments
C:Program Files (x86)Microsoft Visual Studio 12.0VCINCLUDEunordered_map(79) : see declaration of 'std::unordered_map'
test-parameter-pack.cpp(10) : error C3203: 'unordered_map' : unspecialized class template can't be used as a template argument for template parameter 'Container', expected a real type
test-parameter-pack.cpp(8) : error C3211: 'A<int>' : explicit specialization is using partial specialization syntax, use template <> instead
test-parameter-pack.cpp(10) : see declaration of 'A<int>'

我认为这与你对A的部分专业化是错误的有关。编译器无法推导出专用Container的实际模板参数。

看起来你想做一些特别的事情(毕竟这是一种专业化),以防有人用std::unordered_map作为容器类型实例化A。我用以下代码在你的icc现场演示中编译了它。

请注意,Container现在是一个模板模板参数,本身具有任意数量的模板参数。这允许将std::unordered_map的使用检测为使用中的实际容器类型。为了简化到最小的例子,我做了一些简化。

#include <unordered_map>
template <template <typename...> class Container, typename... Args>
struct A
{};
// the following won't compile on some compilers (msvc, icc)
template <typename... Args>
struct A<std::unordered_map, Args...>
{
};

int main(void)
{
    A<std::unordered_map, int, int> a;
    return 0;
}

我在使用ICC 19.0.1时遇到了类似的问题,但使用了C++17 auto模板参数。

解决方案是从值中分离类型并分别推导:

void f(int, int);
//bugged
template<auto F>
struct BindFunc;
template<typename... Args, void(*X)(Args...)> //warning #885: template parameter "Args" is not used in or cannot be deduced from the template argument list of class template "BindFunc<X>"
struct BindFunc<X>
{
};
//correct
template<typename T, T X>
struct BindFunc2Impl;
template<typename... Args, void(*X)(Args...)>
struct BindFunc2Impl<void(*)(Args...), X>
{
};
template<auto F>
struct BindFunc2 : BindFunc2Impl<decltype(F), F>
{
};
//BindFunc<&f> a1; //error
BindFunc2<&f> a2;

https://gcc.godbolt.org/z/gTWzm5