在 C++ 中定义未命名结构时出错 [重复]

Posted

技术标签:

【中文标题】在 C++ 中定义未命名结构时出错 [重复]【英文标题】:Error defining an unnamed structure in c++ [duplicate] 【发布时间】:2021-07-02 02:33:00 【问题描述】:

我的代码有问题,连我的教授都不知道为什么会这样。

他希望我用using Persontype= struct; 定义结构,而不是结构的正常定义。我不明白为什么或有什么区别。

他也不希望我们在 main 中包含 .cpp 文件。

结构的正常定义可以正常工作,但不适用于 this。

错误

In file included from ...\LABOR1TEST\main.cpp:3:
...\LABOR1TEST\test.hpp:12:6: warning: 'void test(const std::vector<<unnamed struct> >&)' used but never defined
 void test(std::vector<PersonType> const &_Personen);
      ^~~~
[100%] Linking CXX executable LABOR1TEST.exe
CMakeFiles\LABOR1TEST.dir/objects.a(main.cpp.obj): In function `main':
.../LABOR1TEST/main.cpp:12: undefined reference to `test(std::vector<._56, std::allocator<._56> > const&)'
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe[3]: *** [CMakeFiles\LABOR1TEST.dir\build.make:120: LABOR1TEST.exe] Error 1
mingw32-make.exe[2]: *** [CMakeFiles\Makefile2:95: CMakeFiles/LABOR1TEST.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:102: CMakeFiles/LABOR1TEST.dir/rule] Error 2
mingw32-make.exe: *** [Makefile:137: LABOR1TEST] Error 2

这是我的代码

main.cpp

#include <iostream>
#include <vector>
#include "test.hpp"

int main() 

    PersonType p;
    p.Name = "Max";
    std::vector<PersonType> TEMPVEC;
    TEMPVEC.push_back(p);
    TEMPVEC.push_back(p);
    test (TEMPVEC);
    return 0;

test.cpp

#include <iostream>
#include <vector>
#include <string>
#include "test.hpp"
void test(std::vector<PersonType> const &_Personen)

    for (auto const  &i : _Personen)
    
    std::cout << i.Name << std::endl;
    

还有我的 test.hpp

#include <vector>
#include <string>
#ifndef LABOR1TEST_TEST_HPP
#define LABOR1TEST_TEST_HPP

using PersonType = struct 
    std::string Name;
;
void test(std::vector<PersonType> const &_Personen);
#endif //LABOR1TEST_TEST_HPP

CMakeLists.txt

cmake_minimum_required(VERSION 3.17)
project(LABOR1TEST)

set(CMAKE_C++_STANDARD 11)

add_executable(LABOR1TEST main.cpp test.cpp test.hpp)

【问题讨论】:

你也需要链接test.cpp。请给你看 CMakeLists.txt @yeputons 好的,它在 C++17 [basic.link]/4.3 中表示在 typedef-declaration 中定义的未命名类的行为就像是出于链接目的该类具有 typedef 名称。所以也许 g++ 是从字面上理解这一点,并且只将该段落应用于 typedef 而不是 using ?我怀疑那是语言的意图,可能是在 using 被添加到语言之前编写的文本并且从未被重新访问过 @yeputons [dcl.typedef]/2 明确表示“这样的 typedef-name 具有与 typedef 说明符引入的语义相同的语义。”所以我倾向于称这是一个 g++ 错误,尽管从技术上讲,该标准是有缺陷的,因为它给出了相互矛盾的要求 @MommeSherif 祝贺您发现了标准中的缺陷和可能的 g++ 错误。不是每个人都可以说他们已经做到了:) @M.M 看看我发现了什么:***.com/questions/48613758/… 【参考方案1】:

我的解释

using PersonType = struct ..... ; 在顶层将在每个翻译单元中生成不同的匿名类型(.cpp 文件,为简单起见),然后在每个翻译单元中为其命名为 PersonType。这个语句发生在test.hpp内部没关系,所有#includes都由预处理器处理,在处理类型时无关紧要。

所以,两个翻译单元(main.cpptest.cpp)中的PersonType 实际上指的是不同的类型。实际上,main.cpp 期望找到带有一个PersonTypetest(vector&lt;PersonType&gt; const &amp;),而test.cpp 只提供了带有另一个PersonTypetest(vector&lt;PersonType&gt; const&amp;),因此会出现链接错误。

是 GCC 错误吗?

如果你摆脱模板并尝试将以下两个翻译单元编译在一起,你可以更好地看到错误:

using Foo = struct ;
void test(Foo);
int main() 
    Foo f;
    test(f);

using Foo = struct ;
void test(Foo) 

我的 GCC 告诉我以下信息:

a.cpp:2:6: error: 'void test(Foo)', declared using unnamed type, is used but never defined [-fpermissive]
    2 | void test(Foo);
      |      ^~~~
a.cpp:1:7: note: 'using Foo = struct<unnamed>' does not refer to the unqualified type, so it is not used for linkage
    1 | using Foo = struct ;
      |       ^~~
a.cpp:2:6: warning: 'void test(Foo)' used but never defined
    2 | void test(Foo);
      |      ^~~~

但是,用typedef struct Foo; 替换using Foo = struct ; 显然可行,以及从我的GCC 切换到我的Clang。

来自 cmets 的 M.M 建议 typedef 应该工作,因为 [basic.link]/4.3

一个命名类([class.pre]),或在 typedef 声明中定义的未命名类,其中该类具有用于链接目的的 typedef 名称([dcl.typedef]);

虽然[dcl.typedef]/2 表示using 引入的名称应该与typedef 具有相同的语义,但它可能会被GCC 解释为过于字面意思(?)以排除using

令人惊讶的是,it was even asked on *** before!

关于您的问题

他希望我使用 Persontype= struct; 来定义结构而不是结构的正常定义。

如果上面的文字是真的,这是一个很奇怪的要求。无法将不同的翻译单元与PersonType 链接起来。我想知道背后的理由是什么,也许您不应该在单个翻译单元之外实际公开PersonType?考虑咨询您的助教或教授。

【讨论】:

实际上,经过一番研究,我不太确定我的解释:g++ 和 clang++ 对我产生不同的结果,以及在using PersonType = struct .....typedef struct ..... PersonType 之间变化。需要进一步调查。 那是真的,我用 cmake 工具链中的 Visual Studio C++ 编译器(在 clion 中)进行了尝试,它工作正常!并且不能在 Linux 中使用 g++ 或 gcc 编译器 谢谢你!你是个英雄,我明天给他看这个,然后再问他。真的非常感谢!!!!

以上是关于在 C++ 中定义未命名结构时出错 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

保存/加载 C++ 数据时出错

尝试在 C++、MinGW 上获取当前进程内存大小时出错

编译类型向量类的私有成员时出错 - C++ [重复]

在 C++ 向量中存储指针时出错

使用引用将结构传递给函数时出错[重复]

linphone - 构建时出错:未定义的引用