我最近玩过gcc
中的概念功能,并且在类的构造函数或成员函数中使用可变参数概念模板时偶然发现了这个错误:
template<typename From, typename To>
concept bool ConvertibleNoNarrow = requires(From f, To t) {
t = { f };
};
class Foo
{
public:
template<ConvertibleNoNarrow<double>... Args>
Foo(Args&&... args) { /*...*/ }
};
使用Foo
时,gcc会显示内部错误:
err.cpp: In substitution of ‘template<class ... Args> requires ConvertibleNoNarrow<Args, double>... Foo::Foo(Args&& ...) [with Args = {double}]’: err.cpp:23:11: required from here err.cpp:13:3: internal compiler error: in tsubst_constraint, at cp/constraint.cc:1956 Foo(Args&&... args) { } ^~~
如果在全局函数中使用相同的签名,则一切都按预期工作:
/* works */
template<ConvertibleNoNarrow<double>... Args>
void Test(Args&&... args) { }
任何人都可以重现这一点,或者知道为什么会发生这种情况以及如何调用现有的错误报告?
修改
我的gcc版本:
gcc (Gentoo 7.2.0 p1.1) 7.2.0 Copyright (C) 2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
答案 0 :(得分:0)
这是gcc(bugzilla link)中的错误。
尽管如此,您可以通过在requires
子句中添加约束来解决此问题。因此,我们会检查每种类型的概念,并相应地返回std::true_type
或std::false_type
。通过这样做,我们可以将std::conjunction_v
与参数包扩展一起使用,以独立地约束每种类型。
class Foo
{
public:
template<typename... Args>
requires std::conjunction_v<std::conditional_t
< ConvertibleNoNarrow<Args, double>
, std::true_type
, std::false_type
>...>
Foo(Args&&... args) { /*...*/ }
};
答案 1 :(得分:0)
与@nyronium的答案类似,但更简单一点,你可以在requires子句中使用fold表达式。
2nd
我测试了GCC 7.3.0上的等价物。