Consider the following sample code, compiled in C++17 mode:
template <typename...>
struct Bar{};
template <typename T, template <typename> typename C>
struct Foo {
int x;
C<T> test_;
};
int main() {
Foo<int, Bar> test;
test.x = 5;
return test.x;
}
Every version of GCC from 7.x all the way to 11 (HEAD) will happily compile it and the executable will return the expected value, as long as the language standard is set to C++17.
Clang, on the other hand, disagrees across every version I've tried:
prog.cc:11:14: error: template template argument has different template parameters than its corresponding template template parameter
Foo<int, Bar> test;
^
prog.cc:1:22: note: template type parameter pack does not match template type parameter in template argument
template <typename...>
^
prog.cc:4:41: note: previous template type parameter declared here
template <typename T, template <typename> typename C>
^
1 error generated.
Interestingly enough, this is basically the same error that GCC outputs when in C++14 (or older) mode:
prog.cc: In function 'int main()':
prog.cc:11:17: error: type/value mismatch at argument 2 in template parameter list for 'template<class T, template<class> class C> struct Foo'
11 | Foo<int, Bar> test;
| ^
prog.cc:11:17: note: expected a template of type 'template<class> class C', got 'template<class ...> struct Bar'
prog.cc:12:10: error: request for member 'x' in 'test', which is of non-class type 'int'
12 | test.x = 5;
| ^
prog.cc:13:17: error: request for member 'x' in 'test', which is of non-class type 'int'
13 | return test.x;
| ^
If my understanding of template parameters from here is correct, then C++17 no longer requires an exact match for the parameter list, but it is unclear to me how that affects parameter packs.
Which compiler is correct here? And is there a way to convince Clang to work for code like this?
Update: HolyBlackCat suggested using the -frelaxed-template-template-args
Clang option, which indeed makes Clang behave similarly to GCC. From the Clang --help
output:
-frelaxed-template-template-args
Enable C++17 relaxed template template argument matching
I suppose I should have found that before posting; my only excuse is that the Clang manual pages are not up to GCC standards on my system.