是否可以传递对 consteval 函数的引用并将其用作附加 return 值?

Is it possible to pass a reference to a consteval function and use it as additional return value?

有时函数的结果不能由单个 return 值表示。例如:相交两条线的函数。人们可能希望函数 return 实际交点以及它们之间的关系(即平行、相同、相交或倾斜)。

让我们假设这个例子,其中交点由某种 class 表示,线的位置关系由一个整数表示,该整数对 4 种可能性中的每一种都有一个指定值:

int IntersectLines(Line l1, Line l2, Point& point);

Point point{};
int result = IntersectLines(l1, l2, point);

这就是我今天实现它的方式,但现在我想知道是否可以有一个类似的实现,但具有 consteval 功能。 LinePoint 有 constexpr 构造函数和所有东西,计算本身也可以在编译时评估。唯一的问题是我想不出有两个 return 值的方法。我已经想到了 std::pair 但更类似于传递引用的解决方案将是首选。如果不存在这样的解决方案,我将不得不退回到 std::pair.

通过引用 (Point& point) 传递 point 是行不通的,因为“表达式未计算为常量”但传递const 引用 (const Point& point) 也不起作用,因为我无法将结果分配给 point。有没有办法让这个工作?

您不能传递对 consteval 函数的引用并让该函数修改引用的目标,除非您在另一个 consteval 函数中这样做。

consteval 函数的调用必须是一个常量表达式,前提是它没有在另一个 consteval 函数中调用。

但是,常量表达式不能修改常量表达式本身计算之外的对象。


consteval 和常用函数中,您可以 return 多个 return 值的 std::pairstd::tuple,例如在调用站点将它们作为结构化绑定检索。

你可以return一个std::pair<Point, Relationship>

示例:

consteval std::pair<Point, Relationship> IntersectLines(const Line& l1, const Line& l2) 
{
    // replace with the real calc below, this is just for show:
    const Point pnt{l1.p1.x + l2.p1.x, l1.p1.y + l2.p1.y};
    const Relationship rel = Relationship::parallel;
    return {pnt, rel};
}

然后这样称呼它:

int main() {
    constexpr Line l1({1,2}, {3,4}), l2({5,6}, {7,8});
    constexpr auto pr = IntersectLines(l1, l2);
    auto&[pnt, rel] = pr;

    return pnt.x + pnt.y; // 14
}

经过优化,生成的程序集很可能会变成类似

的样子
main:
        mov     eax, 14
        ret

Demo