9

I have discovered that the minimal example below works on gcc and clang and even Visual Studio but it does not compile with icc. I am trying to determine whether or not this is valid C++, but I am not able to find the relevant parts of the standard that answer my question since this is several different concepts combined.

// struct with multiple template parameters
template<typename A, typename B = int>
struct C
{

};

// struct that tries to use C's default second parameter without specifying it
template<typename D, template<typename E, typename ...> class F>
struct G
{
  F<D> h;
};

int main()
{
  G<char, C> i;
}

With icc (16.0.3), compilation gives the following error:

struct.cpp(12): error: too few arguments for template template parameter "F"
    F<D> h;

          detected during instantiation of class "G<D, F> [with D=char, F=C]" at line 17

Is this valid C++?

To me it seems like it should be, because C has a default value for its second template parameter, meaning that F<D> with F = C should be a valid construction.

Barry
  • 286,269
  • 29
  • 621
  • 977
ryan
  • 839
  • 4
  • 13
  • Possible duplicate of [Is it required to explicitly list default parameters when using template template parameter?](http://stackoverflow.com/q/24017466/27678) – AndyG Jun 06 '16 at 14:13
  • Have you tried ` template class F`? – Yakk - Adam Nevraumont Jun 06 '16 at 18:11
  • @Yakk: that does not fix the issue, unfortunately. – ryan Jun 07 '16 at 22:59
  • Can someone please explain to me why this works at all when G does not specify even the first template argument for C? I would've expected something like G>. – user2962533 Jun 14 '16 at 12:08
  • The second argument for G is a template template parameter, so we pass in a template class without template parameters. I hope that's helpful, if not, maybe this post explains it better than I can here: http://codingcastles.blogspot.com/2009/04/things-i-didnt-know-about-c-template.html – ryan Jun 14 '16 at 23:37
  • 1
    The title of this question made me chuckle. This is like fuel for people saying C++ is too complicated. – user2962533 Jun 22 '16 at 21:31

1 Answers1

4

I believe this is a gcc/clang bug. This is related to the [still-open] CWG Issue 150. The rationale provided includes:

Default arguments are allowed for the parameters of a template template parameter, and those default arguments alone will be considered in a specialization of the template template parameter within a template definition; any default arguments for the parameters of a template template argument are ignored.

The template template parameter F doesn't have any default arguments - and the default arguments for C are ignored. So we should end up with an ill-formed specialization, as ICC suggests.

In the examples provided in the issue, both gcc and clang seem to implement the rule (neither allows the call to f() and both go through the operator float() path in Mark Mitchell's example.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • Thanks for the link to CWG-150. An important difference here is that we have variadic template parameters, so in this situation it is possible to have a variadic template parameter list of length zero by taking the default template parameter of `B = int`. This is what gcc and clang appear to be doing, but not icc. But the issue referred to in CWG-150 only applies if we were to remove the variadic template parameter list and replace it with just `typename` instead of `typename...`. – ryan Jun 06 '16 at 15:18
  • @ryan Well, this issue predates C++11 by a lot, so it won't refer to variadic templates. But it's ultimately the same concept. – Barry Jun 06 '16 at 15:26
  • Sad: can you think of a justification why they could not first apply template template arg defaults, then the default args of the source template? – Yakk - Adam Nevraumont Jun 07 '16 at 23:26
  • @Yakk No, but I wouldn't put much weight in that. – Barry Jun 08 '16 at 03:09