C ++强制函数参数评估顺序

bre*_*att 21 c++ c++14

我了解当我调用诸如

a(b(),c());
Run Code Online (Sandbox Code Playgroud)

那么就可以在<= C ++ 14中未定义其行为,而在> = C ++ 17中未指定其行为,这是由编译器确定是求值b还是c首先求值。

我想知道强制执行评估命令的最佳方法。我将编译为C ++ 14。

立即想到的是这样的事情:

#include <iostream>

int count = 5;
auto increment(){
    return count++;
}

template <typename A, typename B>
auto diff(A && a, B && b){
   return a - b;
}

int main() {
    auto && a = increment();
    auto && b = increment();
    auto c = diff(a,b);
}
Run Code Online (Sandbox Code Playgroud)

我处于不确定的行为状态吗?或者这是如何“强制”执行评估命令的?

Sto*_*ica 27

分隔语句的分号强加了“在发生之前”的关系。 auto && a = increment()必须先评估。这是有保证的。a在第二次调用之前,返回的临时文件将绑定到引用(并延长其寿命)increment

没有UB。这是强制评估顺序的方式。

这里唯一的陷阱是,如果increment自身返回引用,那么您就需要担心生命周期问题。但是,如果没有生存期问题,例如说它返回了对的引用count,那么从施加的评估中a,仍然不会存在UB b


lub*_*bgr 16

这是强制评估顺序的另一种方法,使用std::initializer_list可以保证评估的从左到右顺序:

#include <numeric> // for accumulate
#include <initializer_list>

template <class T>
auto diff(std::initializer_list<T> args)
{
   return std::accumulate(args.begin(), args.end(), T(0), std::minus<>{});
}

const auto result = diff({increment(), increment()});
Run Code Online (Sandbox Code Playgroud)

这将您限制为相同类型的对象,并且您需要键入其他大括号。