I have found that the following piece of code:
#include <iostream>
#include <vector>
template <typename T>
struct X : std::false_type {};
template <template <typename> class Y, typename U>
struct X<Y<U>> : std::true_type {};
int main() {
if (X<int>())
std::cout << "wrong\n";
if (X<std::vector<double>>())
std::cout << "correct\n";
return 0;
}
Only prints correct
when compiled with g++-7
with -std=c++1z
. Other versions of g++
, clang++
or other std
flags fail to produce correct.
Is this a bug of the current implementation, and this code should not print anything, or is something changed in C++17 which makes this code work as I expect?
This is a result of the adoption of P0522 in C++17, whose motivation was, from the example:
template <template <int> class> void FI(); template <template <auto> class> void FA(); template <auto> struct SA { /* ... */ }; template <int> struct SI { /* ... */ }; FI<SA>(); // OK; error before this paper FA<SI>(); // error template <template <typename> class> void FD(); template <typename, typename = int> struct SD { /* ... */ }; FD<SD>(); // OK; error before this paper (CWG 150)
Previously, the wording in [temp.arg.template] required template template parameters to match in kind exactly. So given:
template <template <class > class P> class X;
template <class T> class A;
template <class T, class U=T> class B;
template <class... > class C;
X<A>
is clearly okay, but X<B>
is ill-formed because B
takes two template parameters (regardless if one is defaulted!) and X<C>
is ill-formed because P
expects one template parameter and C
takes a pack (even if you could form a C
with only a single parameter!)
The new wording loosens the idea of a match to one which makes more sense - if the template template-parameter is at least as specialized as the argument. That makes X<B>
and X<C>
both work.
Hence, in C++17, X<std::vector<double>>
should pick the specialization. But before C++17, it should pick the primary. gcc is doing the right thing.
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