简体   繁体   English

仅使用 header 文件编译 C++.lib?

[英]Compiling a C++ .lib with only header files?

I'm compiling a C++ static library and as all the classes are templated, the class definitions and implementations are all in header files. I'm compiling a C++ static library and as all the classes are templated, the class definitions and implementations are all in header files. As a result, it seems (under visual studio 2005) that I need to create a.cpp file which includes all the other header files in order for it to compile correctly into the library.结果,似乎(在 Visual Studio 2005 下)我需要创建一个包含所有其他 header 文件的.cpp 文件,以便它正确编译到库中。

Why is this?为什么是这样?

The compiler doesn't compile header files since these are meant to be included into source files.编译器不会编译 header 文件,因为这些文件应该包含在源文件中。 Prior to any compilation taking place the preprocessor takes all the code from any included header files and places that code into the source files where they're included, at the very location they're included.在进行任何编译之前,预处理器会从任何包含的 header 文件中获取所有代码,并将该代码放入包含它们的源文件中,就在它们被包含的位置。 If the compiler should compile the headerfiles as well, you'd for example have multiple definitions on many things.如果编译器也应该编译头文件,例如,你会在很多事情上有多个定义。

Example, this is what the preprocessor sees:例如,这是预处理器看到的:

[foo.h]
void foo();

-- --

[mysource.cpp]
#include "foo.h"

int main()
{
   foo();
}

And this is what the compiler sees:这就是编译器看到的:

[mysource.cpp]
void foo();

int main()
{
   foo();
}

Even when you will create a.cpp file you still won't receive anything.即使您将创建一个.cpp 文件,您仍然不会收到任何东西。 You need to instantiate templates in order to put them in the library.您需要实例化模板才能将它们放入库中。

Take a look here http://www.parashift.com/c%2B%2B-faq-lite/templates.html#faq-35.13 about how to instantiate templates with concrete types.看看这里http://www.parashift.com/c%2B%2B-faq-lite/templates.html#faq-35.13关于如何用具体类型实例化模板。

In c++, templates are just a meta-definition of an actual class.在 c++ 中,模板只是实际 class 的元定义。 When you compile a templated class, the compiler actually generates the code for the actual class on the fly for the particular type of data passed in (the template is just a "pattern" to copy).当您编译模板化的 class 时,编译器实际上会为传入的特定类型的数据动态生成实际 class 的代码(模板只是要复制的“模式”)。

eg If you have the following code例如,如果您有以下代码


struct MyTemplate
{
private:
    float MyValue;

public:
    float Get() { return MyValue; }
    void Set(float value) { MyValue = value; }
};

void main()
{
    MyTemplate v1;
    MyTemplate v2;
    v1.Set(5.0f);
    v2.Set(2);
    v2.Get();
}

What the compiler actually sees is编译器实际看到的是


struct CompilerGeneratedNameFor_MyTemplate_float
{
private:
    float MyValue;

public:
    float Get() { return MyValue; }
    void Set(float value) { MyValue = value; }
};

struct CompilerGeneratedNameFor_MyTemplate_int
{
private:
    int MyValue;

public:
    int Get() { return MyValue; }
    void Set(int value) { MyValue = value; }
};

void main()
{
    CompilerGeneratedNameFor_MyTemplate_float v1;
    CompilerGeneratedNameFor_MyTemplate_int v2;
    v1.Set(5.0f);
    v2.Set(2);
    v2.Get();
}

As you can probably see, the compiler doesn't actually know what code to generate, until you actually declare an instance of your template.正如您可能看到的,编译器实际上并不知道要生成什么代码,直到您真正声明了模板的实例。 This means that the template can't be compiled into a library, because it doesn't know what the template will actually end up being.这意味着模板不能编译到库中,因为它不知道模板最终会是什么。 The good news about this is that you don't actually need ANY library to be compiled or included if you just distribute the header files that include the template definition.好消息是,如果您只是分发包含模板定义的 header 文件,则实际上不需要编译或包含任何库。

Also, as a side note, the '#include' pre-compiler command actually just tells the pre-compiler to replace the '#include' with everything from that file.此外,作为旁注,“#include”预编译器命令实际上只是告诉预编译器用该文件中的所有内容替换“#include”。

If all your code is in.h files, then you don't need to compile a static library to use the code.如果您的所有代码都在.h 文件中,那么您无需编译 static 库即可使用该代码。

All the code is available to the library's use at the compilation time, so nothing is needed at link time.所有代码在编译时都可供库使用,因此在链接时不需要任何东西。

You're trying to create something unnecessary.你试图创造一些不必要的东西。 Most C libraries (and all C++ libraries) get distributed as two portions:大多数 C 库(以及所有 C++ 库)作为两个部分分发:

  • Interface ( foo.h )接口 ( foo.h )
  • Implementation ( foo.lib )实现( foo.lib

For C++ template code, all of your library must be compiled by your end-users, because that's how templates work.对于 C++ 模板代码,您的所有库都必须由最终用户编译,因为这就是模板的工作方式。 There's no reason to provide a pre-compiled library.没有理由提供预编译库。 In this case, your can think of your library distribution as this:在这种情况下,您可以将您的库分发视为:

  • Interface ( foo.h )接口 ( foo.h )
  • Implementation ( foo-inl.h )实施( foo-inl.h

As Niel said above, it's useful to have implementations just for your own testing purposes, and it's probably worthwhile distributing those with the library itself.正如 Niel 上面所说的,仅出于您自己的测试目的而拥有实现很有用,并且可能值得将这些实现与库本身一起分发。 So you should have a separate suite of unit tests that exercise your code;所以你应该有一套单独的单元测试来练习你的代码; but those tests shouldn't be part of the library itself.但这些测试不应该是库本身的一部分。

If your library is all implemented in header files, you don't need to build any binary to use it.如果您的库全部在 header 文件中实现,则无需构建任何二进制文件即可使用它。 That said.那说。 I usually create a.cpp file during my initial development phase of header only library.我通常在 header 唯一库的初始开发阶段创建一个.cpp 文件。 Why?为什么? Compilers don't try to compile or even parse your template until it is actually being used.在实际使用模板之前,编译器不会尝试编译甚至解析模板。 Having a.cpp file and have some dummy code there to instantiate the templates help me find syntax errors earlier during development.拥有一个 .cpp 文件并在那里有一些虚拟代码来实例化模板,这有助于我在开发过程中更早地发现语法错误。 So i can add some template code, hit compile, fix syntax error, add more code, compile...etc.所以我可以添加一些模板代码,点击编译,修复语法错误,添加更多代码,编译......等等。 If you every try to hunt down some silly syntax error after adding hundreds of lines of code, you'll know what i mean.如果您在添加数百行代码后都尝试寻找一些愚蠢的语法错误,您就会明白我的意思。 Once my library is ready for unit test, i'll remove the.cpp file and rely on unit testes to drive my development.一旦我的库准备好进行单元测试,我将删除 .cpp 文件并依靠单元测试来推动我的开发。

Also, if your only compile your code using VC++, one thing you need to be aware of is that VC++ doesn't try to compile all template member functions until it is actually used.此外,如果您只使用 VC++ 编译代码,您需要注意的一件事是 VC++ 在实际使用之前不会尝试编译所有模板成员函数。 For example:例如:

template <typename T>
class MyTemplate
{
public:
    MyTemplate() {} // default constructor

    MyTemplate(int) { 
        1 = 2
        // other syntax error code here
    }
};

void f() { MyTemplate<int> myt(); } // compile fine in VC
void g() { MyTemplate<int> myt(1); } // syntax error 

The f() will compile just fine with VC++ 2003, g++ will catch the syntax error. f() 将在 VC++ 2003 中正常编译,g++ 将捕获语法错误。 I think VC8 and VC9 also have the same problem.我认为VC8和VC9也有同样的问题。

Think of Standard Template Library.想想标准模板库。 Your templated classes will be compiled when you utilize them in another project.当您在另一个项目中使用它们时,您的模板类将被编译。

What others have said is true regarding templates not being compiled into the library.其他人所说的关于未编译到库中的模板是正确的。 However, it is still well worth forcing them to be seen by the compiler (by #including them in a.cpp file) as this way they will at least be checked for syntax.但是,仍然值得强制编译器看到它们(通过#将它们包含在 a.cpp 文件中),因为这样至少会检查它们的语法。

You don't need to generate a.lib if all you classes are templates, take a look a boost or the stlport they don't have a.lib that they distribute [1].如果所有类都是模板,则不需要生成 a.lib,看看 boost 或他们没有分发的 .lib 的 stlport [1]。

Templates are compiled when they are used.模板在使用时被编译。

[1] Strictly speaking they distribute libraries for the more advanced features like regular expressions, iostream etc., but auxiliary libraries are used by others templates, the templates by themselves are not distributed in library form. [1] 严格来说,他们为正则表达式、iostream 等更高级的功能分发库,但辅助库被其他模板使用,模板本身不以库的形式分发。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM