Gcc and clang seem to disagree on whether this code should compile or not:
#include <type_traits>
template <typename Signature, int N = 0>
struct MyDelegate { };
template <typename D>
struct signature_traits;
template <template <typename> class Delegate, typename Signature>
struct signature_traits<Delegate<Signature>>
{
using type = Signature;
};
static_assert(std::is_same_v<
void(int, int),
signature_traits<MyDelegate<void(int, int)>>::type
>);
See godbolt output here and try it. I'm siding with clang here, but what does the C++ standard say about this?
A follow-up question - can this be made to work in clang?
Just like in case of the function arguments, template parameters can have their default values. All template parameters with a default value have to be declared at the end of the template parameter list.
For example, given a specialization Stack<int>, “int” is a template argument. Instantiation: This is when the compiler generates a regular class, method, or function by substituting each of the template's parameters with a concrete type.
Template non-type arguments in C++ It is also possible to use non-type arguments (basic/derived data types) i.e., in addition to the type argument T, it can also use other arguments such as strings, function names, constant expressions, and built-in data types.
A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)
This is perfectly valid code, and gcc is right. The "feature" was introduced in C++17. It's not really a feature because it is a defect report. MyDelegate
matches the partial specialization of signature_traits
, and so it should be taken as gcc correctly does. Note that it works because the second template parameter is defaulted.
The reason why clang doesn't compile it is because that defect report has a defect :P. It doesn't introduce the appropriate change in partial ordering, which is not really nice and makes previousy valid code ambiguous again.
It is expected to be fixed soon, but in the meanwhile, clang decided to "hide" the feature behind a flag, -frelaxed-template-template-args.
So, just compile with that flag enabled and you should be fine.
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