使用variadic概念模板时GCC内部错误

gcc internal error when using variadic concept template

本文关键字:GCC 内部 错误 variadic 使用      更新时间:2023-10-16

i最近在gcc中使用了概念功能,并在类的构造函数或类的构造函数中使用variadic概念模板时偶然发现了此错误:

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.

这是GCC(Bugzilla链接)中的一个错误。

但是,您可以通过在requires子句中添加约束来解决问题。因此,我们在每种类型上检查概念,并相应地返回std::true_typestd::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) { /*...*/ }
};

类似于 @nyronium的答案,但是更简单,您可以在"需求"子句中使用折叠表达式。

class Foo
{
public:
    template<typename... Args>
        requires (ConvertibleNoNarrow<Args, double> && ...)
    Foo(Args&&... args) { /*...*/ }
};

我在GCC 7.3.0上测试了等效物。