考虑以下代码:

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.2和g++干线无法通过静态断言。 clang++ 5.0.0和clang++干线可以按预期进行编译和工作。

godbolt.org conformance view

这是g++错误吗?还是有一个为什么不应该在这里遵循推导指南的原因?

在构造函数上添加SFINAE约束似乎可以提供所需的行为:
template <typename... Args,
          typename = std::enable_if_t<sizeof...(Args) == sizeof...(Types)>>
list(Args...)
{
    static_assert(sizeof...(Types) > 0);
}

godbolt.org conformance view

最佳答案

这是gcc bug 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中的示例)。因此,正确的行为是继续进行下一个决胜局,即favors deduction-guides。因此,这应该是list<int, double, char>

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

关于c++ - g++不接受可变参数推导指南,clang++不接受-谁是正确的?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52520408/

10-15 04:30