Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么我会收到一个函数已使用但未定义和已定义但未使用的警告?_C++_Lambda_G++_Compiler Warnings_Unnamed Namespace - Fatal编程技术网

C++ 为什么我会收到一个函数已使用但未定义和已定义但未使用的警告?

C++ 为什么我会收到一个函数已使用但未定义和已定义但未使用的警告?,c++,lambda,g++,compiler-warnings,unnamed-namespace,C++,Lambda,G++,Compiler Warnings,Unnamed Namespace,我遇到了一对不同寻常的编译器警告,它们似乎相互矛盾。以下是我编写的代码: #include <functional> #include <iostream> namespace { std::function<void()> callback = [] { void theRealCallback(); // Forward-declare theRealCallback theRealCallback(); // Invoke

我遇到了一对不同寻常的编译器警告,它们似乎相互矛盾。以下是我编写的代码:

#include <functional>
#include <iostream>

namespace {
  std::function<void()> callback = [] {
    void theRealCallback(); // Forward-declare theRealCallback
    theRealCallback();      // Invoke theRealCallback
  };

  void theRealCallback() {
    std::cout << "theRealCallback was called." << std::endl;
  }
}

int main() {
  callback();
}
这很奇怪,因为第一个警告说我在使用一个函数而没有定义它,第二个警告说我在定义一个函数而没有使用它

运行这个程序确实会产生输出

theRealCallback was called.
程序正常终止

有趣的是,如果不使用未命名的名称空间,而是给名称空间命名,这些警告就会消失,如下所示:

#include <functional>
#include <iostream>

namespace NamedNamespace {
  std::function<void()> callback = [] {
    void theRealCallback();
    theRealCallback();
  };

  void theRealCallback() {
    std::cout << "theRealCallback was called." << std::endl;
  }
}

int main() {
  NamedNamespace::callback();
}
#包括
#包括
名称空间NamedNamespace{
std::函数回调=[]{
无效,否则返回();
theRealCallback();
};
void thereallback(){
std::cout我认为开放性与决定您的程序是否良好相关


按照目前标准的措辞,我认为你的程序格式不正确

基于C++17标准(最终草案):

根据您的声明,lambda将使用外部链接声明回调,因为它是块范围内的函数声明,与其他已声明的实体不匹配

同时,根据
的第二个声明,alcallback
具有内部链接,因为它是未命名命名空间中函数的命名空间范围声明

根据研究,如果一个程序在同一个翻译单元中声明了一个具有内部和外部链接的实体,则该程序是格式不良的。不过,这种格式不良是最近才添加的,原因是解析


正如《化学武器公约》第426期的注释所述,根据《公约》,声明仅涉及同一实体,尽管它们具有相同的联系,这意味着其决议中的不良形式条件不适用

因此,如果我们严格解释这一点,那么程序实际上有两个独立的函数
,一个具有外部链接,一个具有内部链接。具有内部链接的有定义,但具有外部链接的没有。如果是这种情况,则程序违反了一个定义规则,因为调用;在lambda ODR中使用带有外部链接的函数,该函数没有定义。这将使程序格式错误,无需诊断

虽然通过严格阅读标准,这可能是正确的解释,但我认为CWG第426号问题的决议本应适用于此,因为根据上述解释,它永远不会适用。我不知道为什么决议中没有固定提到的问题


应该解析为块范围的声明将匹配封闭命名空间的链接,那么程序将是格式良好的,
ThealCallback
将具有内部链接


您可以看到,如果通过添加
-pedantic errors
标志严格解释标准,则GCC认为程序格式错误,这将导致程序发出错误而不是警告


当然,解决这个问题最简单的方法是在命名空间范围的lambda之外转发declare
void theralcallback();
,在这种情况下,链接肯定是内部的,任何块范围声明都会引用该声明,并承担其链接



如果名称空间已命名,则这不是问题,因为这样名称空间范围声明也将具有外部链接。

您不能向前声明TheherealCallback()在lambda的内部。把它移到上面,它应该会工作。我明天早上会回来。你的帖子很有趣。重量级人物会插话来解决这个问题。我感觉你的编译器正在原谅它不应该做的事情。但是没有做律师的事……晚安。我得出了类似的结论,只是名字没有实际上表示相同的函数,因此[basic.link]中的规则/7不适用;它只是违反了ODR。关于426问题的说明指出了这一点,但这一点似乎从未得到解决。@Aschepper我已经添加了一段关于这一点的内容。如果这与您的结论不同,请告诉我。谢谢您的澄清。您为我节省了很多作业。
#include <functional>
#include <iostream>

namespace NamedNamespace {
  std::function<void()> callback = [] {
    void theRealCallback();
    theRealCallback();
  };

  void theRealCallback() {
    std::cout << "theRealCallback was called." << std::endl;
  }
}

int main() {
  NamedNamespace::callback();
}