推导出第一个模板参数,其他模板参数默认

Gcc 和 clang 似乎不同意这段代码是否应该编译:

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

在此处查看 godbolt 输出并尝试一下.我在这里支持 clang,但 C++ 标准对此有何评论?

See godbolt output here and try it. I'm siding with clang here, but what does the C++ standard say about this?

一个后续问题 - 这可以在 clang 中工作吗?

A follow-up question - can this be made to work in clang?

推荐答案

这是完全有效的代码,gcc 是正确的.功能"是 在 C++17 中引入.这并不是真正的功能,因为它是一份缺陷报告.MyDelegate 匹配 signature_traits 的部分特化,所以它应该像 gcc 一样正确.请注意,它有效,因为第二个模板参数是默认的.

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.

clang 不编译它的原因是因为那个缺陷报告有一个缺陷:P.它没有在偏序中引入适当的变化,这是不太好,使之前的有效代码再次变得模棱两可.

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.

预计很快就会修复,但与此同时,clang 决定将功能隐藏"在一个标志后面,-frelaxed-template-template-args.

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.

相关文章