杂数演绎指南不是由 g++ 采取的,由 clang++ 采取 - 谁是正确的

Variadic deduction guide not taken by g++, taken by clang++ - who is correct?

本文关键字:clang++ 采取 演绎 g++      更新时间:2023-10-16

请考虑以下代码:

template <typename... Types>
struct list
{
    template <typename... Args>
    list(Args...) 
    {
        static_assert(sizeof...(Types) > 0);
    }
};
template <typename... Args>
list(Args...) -> list<Args...>;
int main()
{
    list l{0, 0.1, 'a'};
}

我希望decltype(l)list<int, double, char>.不幸的是,g++ 7.2g++ 主干无法实现静态断言。clang++ 5.0.0clang++ 主干编译并按预期工作。

godbolt.org 一致性视图

这是一个 g++ 错误吗?还是有理由不在这里遵循扣除指南


在构造函数上添加 SFINAE 约束似乎提供了所需的行为:

template <typename... Args, 
          typename = std::enable_if_t<sizeof...(Args) == sizeof...(Types)>>
list(Args...) 
{
    static_assert(sizeof...(Types) > 0);
}

godbolt.org 一致性视图

这是 gcc 错误 80871。问题是,我们最终得到了这组要扣除的候选人:

template <class... Types, class... Args>
list<Types...> __f(Args... ); // constructor
template <class... Args>
list<Args...>  __f(Args... ); // deduction-guide

两者都是有效的(在第一种情况下Types...可以推断为空),但这里的调用应该是模棱两可的 - 两者都不比另一个更专业。 Types...不参与此处的排序(类似于 [temp.deduct.partial]/12 中的示例)。因此,正确的行为是进入下一个决胜局,这有利于演绎指南。因此,这应该是一个list<int, double, char>

但是,gcc的行为是支持构造函数,因此static_assert触发器,因为在这种情况下Types...确实是空的。