g ++不采用可变参数推导指南,clang ++不采用可变推导指南-谁是正确的? [英] Variadic deduction guide not taken by g++, taken by clang++ - who is correct?
问题描述
考虑以下代码:
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 ++ trunk 无法通过静态断言。 clang ++ 5.0.0 和 clang ++ trunk 可以按预期进行编译和工作。
I would expect decltype(l)
to be list<int, double, char>
. Unfortunately, g++ 7.2 and g++ trunk fail the static assertion. clang++ 5.0.0 and clang++ trunk compile and work as expected.
这是 g ++ 错误?还是有一个为什么不应该在此遵循《扣除指南》的原因?
Is this a g++ bug? Or Is there a reason why the deduction guide should not be followed here?
添加一个构造函数上的SFINAE约束似乎提供了所需的行为:
Adding a SFINAE constraint on the constructor seems to provide the desired behavior:
template <typename... Args,
typename = std::enable_if_t<sizeof...(Args) == sizeof...(Types)>>
list(Args...)
{
static_assert(sizeof...(Types) > 0);
}
推荐答案
这是 gcc错误80871 。问题是,我们最终得到这组可推论的候选人:
This is gcc bug 80871. The issue is, we end up with this set of candidates for deduction:
template <class... Types, class... Args>
list<Types...> __f(Args... ); // constructor
template <class... Args>
list<Args...> __f(Args... ); // deduction-guide
两者均有效( Types ...
在第一种情况下可以推论为空),但此处的调用应该是模棱两可的-两者都不比另一个更专业。 类型...
不参与此处的订购(类似于 [temp.deduct.partial] / 12 )。因此,正确的行为是继续进行下一个决胜局,优惠推导指南。因此,这应该是 list< int,double,char>
。
Both are valid (Types...
can deduce as empty in the first case), but the call here should be ambiguous - neither is more specialized than the other. Types...
does not participate in ordering here (similar to the example in [temp.deduct.partial]/12). So the correct behavior is to proceed to the next tiebreaker, which favors deduction-guides. Hence, this should be a list<int, double, char>
.
但是,gcc的行为是有利于构造函数,因此 static_assert
触发是因为 Types ...
在这种情况下确实为空。
However, gcc's behavior is to favor the constructor, hence the static_assert
triggers becuase Types...
would indeed be empty in that situation.
这篇关于g ++不采用可变参数推导指南,clang ++不采用可变推导指南-谁是正确的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!