Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template parameter pack provokes error while explicit parameters not

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:

  • gcc 4.7.3, 4.8.1, 4.8.2, 4.9.0, 4.9.2
  • clang 3.3, 3.4.1, 3.5.0, 3.5.1, 3.6.0rc2

Does not work:

  • msvc-12.0 (2013) update 4
  • icc-13.0.1

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>'
like image 567
Marek Kurdej Avatar asked Oct 31 '22 09:10

Marek Kurdej


1 Answers

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;
}
like image 52
haavee Avatar answered Nov 15 '22 04:11

haavee