【问题标题】:C++ lambda default arguments compiler misbehavior?C ++ lambda默认参数编译器行为不当?
【发布时间】:2021-01-30 20:23:45
【问题描述】:

以下哪些 C++ lambdas/语句应该根据最新的 C++ 规范工作?

相关情况下的上下文:see here

我在使用 clang 11.0.0 和 gcc 10.2.1 的 Fedora 33 上使用-std=c++17 测试了以下代码 sn-ps。

更新:__PRETTY_FUNCTION__ 替换为 __func__ 以符合标准。可以观察到相同的行为。

更新 2: Example 使用 const char * s = __func__ 作为默认参数来验证它在函数范围内是否有效(感谢 @BenVoigt)。


1。 LLVM __func__ 在 lambda 默认参数中

void clang() {
  [](const char* c = __func__) {std::cout << c << std::endl;}();
}

预期行为(CLANG):

  • 打印出clang\nvoid clang() for __PRETTY_FUNCTION__

观察到的行为(CLANG):

  • 编译器警告:warning: predefined identifier is only valid inside function [-Wpredefined-identifier-outside-function]
  • 打印出\ntop level() for __PRETTY_FUNCTION__

2。 GCC 忽略语句

template <typename L>
constexpr std::string_view methodName(L l) { return l(); }
#define __METHOD_NAME__ (\
  __func__, /* needed for pointer to work */ \
  methodName([](const char* c = __func__) {return std::string_view(c);}) \
)
void gcc1() {
  std::cout << [](const char* c = __func__) { return c; }() << std::endl;  // GCC: This statement doesn't do anything
  std::cout << [](const char* c = __func__) { return c; }("gcc") << std::endl;
  std::cout << __METHOD_NAME__ << std::endl;  // GCC: This statement somehow conflicts with the statements above
}
void gcc2() {
  std::cout << __METHOD_NAME__ << std::endl;  // GCC: This statement itself works
}

预期输出 (GCC):

gcc1
gcc
gcc1
gcc2

观察到的输出 (GCC):

gcc
gcc2

3。 GCC编译错误

void gcc3() {
  std::string_view s = [](const char* c = __func__) { return std::string_view(c); }();
  std::cout << s << std::endl;
}

预期行为 (GCC): 编译没有问题。

观察到的行为 (GCC): error: internal compiler error: in finish_expr_stmt

【问题讨论】:

  • @Enrico:“改为定义函数”是什么意思? “本地函数”的 g++ 扩展?本地定义的类类型的成员函数?
  • 我指的是使用函数而不是 lambda 函数对象。但我没有理解问题的重点,即这些__variables__ 的行为方式,lambdas 也只是一个调节这些变量所指内容的工具。 (可能我仍然误解了这个问题。)

标签: c++ gcc lambda clang c++17


【解决方案1】:

[class.local] 本地类在封闭作用域的范围内,并且对函数外部的名称具有与封闭函数相同的访问权限。 [注意:本地类中的声明不能直接使用(6.2)封闭范围内的本地实体。 ——尾注]

lambda 是一个本地类,因此它不能使用封闭范围(例如__func__)中的变量,除非是在其捕获子句中。

【讨论】:

  • 感谢您的澄清。您是否看到任何将__func__(作为宏)传递给constexpr methodName()而不是template-handling the string character by character或等待似乎尚未在任何地方实现的C++20 std::basic_fixed_string as template parameter的方法?
  • @darkdragon __func__ 不是宏,而是真正的变量。
  • 我需要一个像#define __METHOD_NAME__ methodName(__func__) 这样的,以便在我的记录器中使用。
  • 我不太清楚为什么你不能按原样使用__func____PRETTY_FUNCTION__。为什么要将它包装在 lambda 或其他任何东西中?
  • 如果您在定义记录器宏或函数时遇到问题,请询问有关定义记录器宏或函数的问题。有无数的记录器可以打印函数名称。举例说明为什么他们的策略不适合你。
猜你喜欢
  • 1970-01-01
  • 2016-01-17
  • 2011-08-10
  • 2011-09-06
  • 1970-01-01
  • 2011-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多