CMake / g ++在链接

时间:2017-01-15 18:02:16

标签: c++ linker g++ undefined c++14

[解决]
所以我有一个编译器/翻译器,用于我正在研究的编程语言 在过去,该项目是不受管理的,我使用了一些聪明(但可能很糟糕)的技巧来编译这个东西,它一切正常并且运行良好。
最近,我获得了CLion学生许可,我爱上了IDE,所以我决定将我的编译器迁移到CLion项目。
现在我遇到了编译问题,链接器会抛出一堆“Undefined Reference”错误。我看过我的包括警卫,包括和其他东西,但我似乎无法找到造成这种情况的原因...
这是链接器给我的输出的一部分

[ 86%] Linking CXX executable Compiler.exe
C:/.../Compiler/src/Parser/Parser.cpp:133: undefined reference to `void Dragoon::AST_Node::add_child<Dragoon::For_Node>(std::shared_ptr<Dragoon::For_Node>)'
C:/.../Compiler/src/Parser/Parser.cpp:134: undefined reference to `void Dragoon::AST_Node::add_child<Dragoon::For_Body_Node>(std::shared_ptr<Dragoon::For_Body_Node>)'

Parser.cpp 是一个很长的文件,但这里有一些相关的部分:

#include "Parser.hpp"

namespace Dragoon
{
    std::vector<Error_Msg> Parser::parse(Statement stm, std::shared_ptr<AST_Node> par_node, uint level)
    {

这是文件的开头,之前的唯一行是与作者,日期,...的评论行 我还省略了解析器的构造函数和启动解析过程的解析方法。这些都在命名空间内但在显示的方法之前。 (显示的方法是抛出错误的方法)

            par_ptr->add_child(for_node);
            for_node->add_child(body_node);
            this->m_current_node = body_node;

            std::vector<Error_Msg> parse_errors = this->parse(init, for_node, level + 1);

这些是第130到135行(生成错误的那些)

现在, AST_Node.hpp

#include <string>
#include <memory>
#include <vector>
#include "Node_Classes.h"
#include "../Constants/Aliases.h"

#ifndef COMPILER_AST_NODE_HPP
#define COMPILER_AST_NODE_HPP

namespace Dragoon
{
    class AST_Node
    {
        protected:
            std::string m_class;

            std::shared_ptr<AST_Node> m_parent;

            std::vector<std::shared_ptr<AST_Node>> m_children;

        public:
            AST_Node();

            AST_Node(std::shared_ptr<AST_Node> m_parent, std::string node_class);

            std::shared_ptr<AST_Node> get_parent(void);

            std::shared_ptr<AST_Node> get_child(uint index);

            int num_children(void);

            template<typename T>

            void add_child(std::shared_ptr<T> ch);

            std::string node_class(void);

            virtual std::string to_string(void);

            virtual std::string get_type(void);

            void print(uint level);
    };
}

#endif //COMPILER_AST_NODE_HPP

AST_Node.cpp (我再次留下一些部分,不要用不相关的代码超载你,如果有人想看到不同的部分,我会更新问题)

#include "AST_Node.hpp"

namespace Dragoon
{

问题方法:

template<typename T>

void AST_Node::add_child(std::shared_ptr<T> ch)
{
    this->m_children.push_back(ch);
}

我的项目结构如下:

Compiler
    \_cmake-build-debug (default cmake dir, haven't touched it)
    \_Example Code (My programming language, will be used to test the compiler)
    \_src
        \_Collections (Arrays of constants and such)
        \_Constants (Things like error codes etc.)
        \_Lexer (All Lexer-relevant code)
        \_Parser (All Parser-relevant code, this is where both of the shown files are)
        \_Symbol Table (Symbol and Function Table)
        \_Utils (Several utility functions, like concatenating an array to a string etc., A bunch of the other "undef. reference" errors also point here)
        \_Some C++ code that doesn't really fit in any folder (Error_Msg class for instance)
        \_CMakeList.txt

我的 CMakeList.txt

cmake_minimum_required(VERSION 3.6)
project(Compiler C CXX)

add_definitions(-D_WIN32)

set(SOURCE_FILES    ...
                    "src/Parser/Parser.cpp"
                    ...
                    "src/Parser/AST_Node.cpp"
                    ...)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y")

add_executable(Compiler ${SOURCE_FILES})

我遗漏了源文件列表中的大部分文件以便于阅读,但我显示的文件顺序相同。

我已经完成了这个帖子:What is an undefined reference/unresolved external symbol error and how do I fix it?

但我能想到的唯一没有做的就是检查我的源文件的列出顺序(如果它甚至相关?)

如果有人对此为何会有任何提示,我们将不胜感激

除了C ++ std之外,我没有使用任何外部库。 libs和STL libs。

我在Windows 10上使用g ++ 4.9.3运行CLion 2016.3。

我忘了在C ++中你不能将模板的定义/声明分开。感谢axalis回答我的问题

1 个答案:

答案 0 :(得分:0)

问题是,您的模板化方法位于* .cpp文件中。这不起作用,因为在编译.cpp文件时,编译器不知道它将被实例化的模板参数。

这个问题有两个基本解决方案:

1)将方法定义与模板声明(推荐)一起放在头文件中

2)在.cpp文件中添加显式模板实例化:

template class Dragoon::AST_Node<Dragoon::For_Node>;
template class Dragoon::AST_Node<Dragoon::For_Body_Node>;

这不是那么推荐的,因为你可以注意到,模板需要为它将要使用的每一组参数显式实例化,这在一般情况下是不实际的(你可能根本不知道 - 如果有的话) else将在未来用作模板参数,需要添加显式实例化。)