Advertisement
Guest User

Potential edit #2.

a guest
Dec 8th, 2016
55
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Consider the following code:
  2.  
  3. template<typename>
  4. struct One {};
  5.  
  6. template<typename, typename>
  7. struct Two {};
  8.  
  9. template<template<typename...> class TTP, typename...>
  10. struct SS;
  11.  
  12. #ifdef TEST_TTP
  13. template<template<typename> class OneParam,
  14. typename... Ts>
  15. struct SS<OneParam, Ts...> {};
  16.  
  17. template<template<typename, typename> class TwoParam,
  18. typename... Ts>
  19. struct SS<TwoParam, Ts...> {};
  20. #else // TEST_TTP
  21. template<template<typename> class OneParam,
  22. typename TParam>
  23. struct SS<OneParam, TParam> {};
  24.  
  25. template<template<typename, typename> class TwoParam,
  26. typename TParam1,
  27. typename TParam2>
  28. struct SS<TwoParam, TParam1, TParam2> {};
  29. #endif // TEST_TTP
  30.  
  31. int main() {
  32. SS<One, int> ssoi;
  33. SS<Two, int, int> sstii;
  34. }
  35.  
  36. This code will compile properly on Clang, GCC, and MSVC, if `TEST_TTP` isn't defined. However, if it _is_ defined...
  37.  
  38. * The code compiles properly on GCC, indicating that it recognises that `OneParam` and `TwoParam` are distinct from `TTP` in the primary template.
  39. * Clang fails to recognise that `OneParam` specialises `TTP`, causing it to emit two errors (the first being that the partial specialisation doesn't specialise any template parameters, and the second being that `OneParam` conflicts with the previously-declared template template parameter). It then emits similar errors for `TwoParam` (the first is identical, while the second says that the template template parameter has too many parameters), and an error for each instantiation of `SS` (because it considers the template to be undefined), for a total of 6 errors.
  40. * MSVC emits similar errors to Clang, but more concisely: It emits C3855 (`OneParam` is incompatible with the primary template), and a C2079 (variable uses undefined type) for each instantiation of `SS`, for a total of 3 errors.
  41.  
  42. Demonstrated live [on Coliru][1].
  43.  
  44. ----
  45.  
  46. From my testing:
  47.  
  48. **GCC allows a template with a template template parameter which takes a variadic parameter pack to be partially specialised based solely on the number of parameters that template template parameter takes. Clang and MSVC do not.**
  49.  
  50. template<template<typename...> class T> struct S;
  51. template<template<typename> class T> struct S<T> {}; // Only works with GCC.
  52. template<template<typename, typename> class T> struct S<T> {}; // Only works with GCC.
  53.  
  54. **Clang and MSVC are fine with this if other parameters are also specialised, however.**
  55.  
  56. template<template<typename...> class T, typename... Ts> struct S;
  57.  
  58. template<template<typename> class T,
  59. typename TParam>
  60. struct S<T, TParam> {};
  61.  
  62. template<template<typename, typename> class T,
  63. typename TParam1,
  64. typename TParam2>
  65. struct S<T, TParam1, TParam2> {};
  66.  
  67. It would thus appear that either the former isn't legal C++, or it isn't properly supported by Clang and MSVC. So, the question is this:
  68.  
  69. **Considering this, what is the proper, legal syntax for partially specialising a template, which contains a template template parameter, based on the number of parameters that template template parameter takes? If there is no legal syntax for this, is supporting it a GCC extension and/or bug?**
  70.  
  71. <sup>If a full record of the tests I performed, along with the original example which prompted this question, are desired, please see the edit history.</sup>
  72.  
  73. [1]: http://coliru.stacked-crooked.com/a/f145f13504935246
Advertisement
RAW Paste Data Copied
Advertisement