考虑以下代码:
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/