C++17 中的 Lambda 表达式:尾随 return 类型与 static_cast 类型转换

Lambda expression in C++17: trailing return type vs static_cast for type conversion

如何将lambda表达式的int正确转换为longinside/outside?如何正确检查 lambda 中的数学溢出?

int n = 12; // input parameter from std::cin
int a = 23; // input parameter from std::cin
int i = 34; // input parameter from std::cin
auto f = [n, a] (int i) { return a * (n - (i - 1)); };
auto result = f(i);

lambda 整数 inside/outside 相乘后检查溢出的最佳方法是什么?

auto result = f(i);
if ((result > std::numeric_limits<int>::max()) || (result < std::numeric_limits<int>::min())) {
    cout << "overflow was detected" << endl;
}

我是否需要将 TRT(尾随 return 类型)-> long 添加到 lambda 以便从 int 正确转换为 long

auto f = [n, a] (int i) -> long { return a * (n - (i - 1)); };

我是否需要将 static_cast 添加到 lambda 中以便从 int 正确转换为 long:

auto f = [n, a] (int i) { return static_cast<long>(a) * (n - (i - 1)); };

或者,我可能需要合并这个?

auto f = [n, a] (int i) -> long { return static_cast<long>(a) * (n - (i - 1)); };

或者,我需要写 lambda 的类型?

std::function< long( int ) > f = [n, a] (int i) { return a * (n - (i - 1)); };

你的问题的第一部分是duplicate(尽管C问题,C++没有区别,并且有重复的including C++)。最重要的一点:您无法检测到有符号整数溢出 after 乘法,因为它已经导致了未定义的行为——除非您在下一个更大的数据类型中进行计算;但是请注意,许多(但不是全部!)平台(包括现代 PC 硬件上的 Windows)上的 intlong 具有相同的大小,因此切换到 long 不是保证避免溢出!如果要安全起见,请使用 <cstdint> header 中的数据类型(例如 int16_tint32_tint64_t)。如果您有某些特定原因坚持使用 int,则必须投入一些额外的工作才能保证下一个更大的类型。不过,这个问题并不特定于 lambda,而是涉及 any 乘法(甚至加法)。

保证特定的 return 类型(同样,问题不是特定于 lambdas,而是特定于 any 类型的自动推导,无论是 return 类型或自动变量),这两种方法都很有价值(显式尾随 return 类型和强制转换),但是,如前所述,结果确实不同!

仅应用尾随 return 类型等同于具有

[n, a] (int i) { return static_cast<long>(a * (n - (i - 1))); };
//                                         ^               ^

请注意,强制转换围绕 整个 计算进行,即。 e.在 计算之后 完成转换,仍然在 int 中完成。如果 int 和 long do 的大小不同,结果可能与您自己的转换变体不同:

[n, a] (int i) { return static_cast<long>(a) * (n - (i - 1)); };

因为这已经强制执行了 long 中的乘法(但不是减法!——即使要强制执行这些,您也需要强制转换 i)。此转换完全足以获得所需的 return 类型;一个明确的尾随 return 类型(另外)更清楚地显示了 lambda 实际上 return 的内容,而无需查看实现。如果您有更复杂的 lambda,这将特别有用,如果您有多个出口点,它可以帮助保证一致的 return 类型。