Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deducing first template argument with other template parameters defaulted

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?

like image 937
Alexander Kondratskiy Avatar asked Jan 25 '18 15:01

Alexander Kondratskiy


People also ask

Can template parameters have default values?

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.

Which is correct example of template parameters?

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.

Can we pass Nontype parameters to templates?

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.

What are template arguments enlist types of template arguments?

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.)


1 Answers

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.

like image 152
Rakete1111 Avatar answered Oct 19 '22 03:10

Rakete1111