The following code (live demo) works fine on clang/gcc, but fails to compiler on icc and msvc.
The only difference is the use of template parameter pack in class A
, whereas class B
is given all template parameters explicitly.
What's the correct behavior? Is the code incorrect? Am I missing something? Or is it just the fact that msvc/icc are not standard-compliant?
Update
Compiler versions tested:
Works:
Does not work:
The code
#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;
}
Error on 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>
^
Error on 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>'
I think it has to do with the fact your partial specialisation of A
is wrong. The compiler cannot deduce the actual template arguments of the specialised Container
.
It looks like you want to do something special (it is a specialisation after all) in case someone instantiates A
with std::unordered_map
as container type. I got it to compile on your live demo with icc with the following code.
Note that the Container
is now a template template parameter, taking an arbitrary amount of template parameters itself. This allows detection of usage of std::unordered_map
as actual container type in use. I did simplify a bit in order to reduce to the minimal example.
#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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With