我一直在开发一个主要是模板函数的库,并设法通过以下方式保持组织(在某种程度上):
// MyLib.h
class MyLib
{
template<class T>
static void Func1()
{
}
template<class T>
static void Func2()
{
}
};
Run Code Online (Sandbox Code Playgroud)
很明显,这样会打电话:
MyLib::Func1();
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,随着更多功能的添加,这会变得非常难看.至少,我想把它分成不同的文件!
我最初考虑在MyLib命名空间中的单独文件中定义批量函数,然后使用a MyLib.h来合并所有这些函数,但我不断收到大量的链接器错误 - 当然,如果建议,我可以仔细研究一下这种方法.
有什么想法吗?
PS:由于大多数这些函数具有不同的目标,因此将它们分组在我们实例化对象的类下是没有意义的.我在class这里使用过,所以我不必担心我定义函数的顺序(内部函数之间也存在相互依赖关系MyLib).
链接器错误:
所以基本结构是这样的:我有两个类(比如A和B)编译到静态库和一个运行这些类的实例的主应用程序.这些类A和B使用函数MyLib.当A&B正在编译时,我收到LNK4006警告,指出属于的符号MyLib已经在项目中的OBJ文件中定义,并且忽略它.
当它归结为应用程序时,它变成一个LNK2005错误,表明它已经在A&B 的OBJ文件中定义.
更新: 谢谢Mike& Mathieu的内联想法 - 这就是问题所在!
除了一个问题:我有一些我明确专门的模板函数,这些函数导致already defined错误(LNK2005):
template<class t> int Cvt(){}
template<> int Cvt<unsigned char>(){return 1;}
template<> int Cvt<char>(){return 2;}
template<> int Cvt<unsigned short>(){return 3;}
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
Conlusion:
通过在单独的文件中定义模板函数解决了显式特化问题 - 感谢您的帮助!
您应该更喜欢使用静态方法在您的类上使用命名空间:
using myNamespace::MyFunc;(注意:写入是不好的做法using myNamespace;,你应该避免这种做法)现在,让我们谈谈组织:
Hello, World!打印而包含整个世界,而商品标题可以提供帮助(例如,为一些懒惰的程序员做一些包含的标题使用)[1]这就是我的意思:
#include "lib/string/manip.hpp" // Okay, this files come from "lib"
int main(int argc, char* argv[])
{
std::string s;
lib::string::manip(s); // Same hierarchy, easy to remember the header
return 0;
}
Run Code Online (Sandbox Code Playgroud)
一个激励的例子?Boost做到了(带商品标题).
而且更重要的是这并没有太大的成本:只需更换class由namespace和删除static关键字,这是所有乡亲.
对于链接器问题:所有未模板化的方法都应该声明为inline(尝试避免它,除非它们是单行)或者在标题之外定义(在单独的.cpp文件中).
更新:
模板特化的问题在于你最终定义了一个现在的"普通"方法:一旦你修复了每个参数,就不再有关于它的模板了.因此,解决方案就像您对正常函数所做的那样:在头文件中声明和在源文件中定义(因此只有一次).
更具体地说明这个奇怪的错误:C++的问题是每个源文件都是独立编译的:预处理器将采用include并实际创建一个文本文件,其中包含每个包含的文件(按顺序)和然后你的来源在最后.编译器获取此文件并生成".o"文件(对于gcc).然后链接器启动并尝试从所有这些".o"文件中实际创建库(或二进制文件),并检查每个方法是否只定义一次,否则它将如何在多个定义之间进行选择(遗憾的是不会检查它们是否相同......)?
虽然模板方法和类有一个特殊的允许,它在所有实例化中(每个模板参数组合的一个实例)中选取一个(随机).当然,这假设所有这些都是相同的,你最终会因为以下事情而头疼:
// foo.h
template <class T> int foo(T) { return 10; }
// foo.cpp
#include "foo.h"
char a;
std::cout << foo(a) << std::endl;
// bar.cpp
#include "foo.h"
template <> int foo<char>(char) { return 20; }
char b;
std::cout << foo(b) << std::endl;
Run Code Online (Sandbox Code Playgroud)
这两行都将打印相同的输出,无论是10还是20都是未知的,并且可能会在构建之间发生变化!
| 归档时间: |
|
| 查看次数: |
4208 次 |
| 最近记录: |