以下代码(live demo)在clang / gcc上运行正常,但无法在icc和msvc上编译。
唯一的区别是在class A
中使用模板参数包,而class B
明确地给出了所有模板参数。
正确的行为是什么?代码不正确吗?我错过了什么吗? 或者只是msvc / icc不符合标准这一事实?
更新
测试的编译器版本:
使用:
不起作用:
代码
#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 update 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.0\VC\INCLUDE\unordered_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>'
答案 0 :(得分:0)
我认为这与A
的部分专业化错误有关。编译器无法推断出专用Container
的实际模板参数。
看起来你想要做一些特殊的事情(毕竟这是一个专业化),以防有人以A
作为容器类型实例化std::unordered_map
。我使用以下代码在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;
}
答案 1 :(得分: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;