该项目的目标是创建一个分发库。在过去,我使用了前向声明,所以我不必分发一堆头文件和库。但是,我现在正试图通过切换到模板来消除代码重复,并遇到了一些问题。
首先,一个简单的示例项目显示当前正在运行的内容:
//LibraryDep1.h
class LibraryDep1
{
public:
LibraryDep1(void) {};
virtual ~LibraryDep1(void) {};
template <typename T>
int TestFunction(T value)
{
std::cout << value << std::endl;
return 0;
}
};
//LibraryInclude.h
class LibraryDep1; //forward declare
class LibraryInclude
{
private:
LibraryDep1* mLibDep1;
public:
LibraryInclude(void);
virtual ~LibraryInclude(void);
int TestFunction(int value);
int TestFunction(std::string value);
};
//LibraryInclude.cpp
#include "LibraryInclude.h"
#include "LibraryDep1.h"
LibraryInclude::LibraryInclude(void)
{
this->mLibDep1 = new LibraryDep1();
}
LibraryInclude::~LibraryInclude(void)
{
delete this->mLibDep1;
}
int LibraryInclude::TestFunction(int value)
{
return this->mLibDep1->TestFunction(value);
}
int LibraryInclude::TestFunction(std::string value)
{
return this->mLibDep1->TestFunction(value);
}
//main.cpp
#include <tchar.h>
#include "LibraryInclude.h"
int _tmain(int argc, _TCHAR* argv[])
{
LibraryInclude inclLibrary;
inclLibrary.TestFunction(77);
inclLibrary.TestFunction("test");
}
这给出了预期的输出:
77
test
但是,LibraryInclude::TestFunction
的重载可以用模板函数替换,以进一步减少代码重复:
//LibraryInclude.h
class LibraryDep1; //forward declare
class LibraryInclude
{
private:
LibraryDep1* mLibDep1;
public:
LibraryInclude(void);
virtual ~LibraryInclude(void);
template <typename T>
int TestFunction(T value) {
return mLibDep1->TestFunction(value);
}
};
现在的问题是我使用的是mLibDep1而没有包含完整的实现,这给我一个未定义的类型编译错误。这意味着我需要在LibraryInclude.h中#include "LibraryDep1.h"
,因此要求我将LibraryInclude.h和LibraryDep1.h分发给我的库。这是一个简单的例子,如果我要切换到使用模板化版本的LibraryInclude,真正的项目有许多头文件需要分发。
我的问题是,有没有办法避免不得不用我的库分发一堆包含文件并消除代码重复?或者,我最好只是在分布式头文件中重载所有已知类型(大大降低库灵活性)并仅将模板保留在底层类中?
答案 0 :(得分:1)
没有。目前没有办法做你想要的。当编译器供应商开始实施'export'关键字时,你会很幸运。目前我只知道Comeau这样做。这个关键词已存在多年,所以在其他关键词实现之前我不会屏住呼吸。
答案 1 :(得分:1)
一个非常有限和丑陋的解决方案是:
//LibraryDep1.h
#pragma once
#include <iostream>
class LibraryDep1
{
public:
LibraryDep1(void) {};
virtual ~LibraryDep1(void) {};
template <typename T>
int TestFunction(T value)
{
std::cout << value << std::endl;
return 0;
}
};
//LibraryInclude.h
#pragma once
class LibraryDep1; //forward declare
class LibraryInclude
{
private:
LibraryDep1* mLibDep1;
public:
LibraryInclude(void);
virtual ~LibraryInclude(void);
template <typename T>
int TestFunction(T value);
};
//LibraryInclude.cpp
#include "LibraryInclude.h"
#include "LibraryDep1.h"
#include <string>
LibraryInclude::LibraryInclude(void)
{
mLibDep1 = new LibraryDep1();
}
LibraryInclude::~LibraryInclude(void)
{
}
// only to save some typing when only forwaring calls
#define LI_TESTFUNCTION( TYPE ) \
template<> \
int LibraryInclude::TestFunction<TYPE>( TYPE value ) {\
return mLibDep1->TestFunction(value); \
}
// the allowed specializations, everything else causes link errors
LI_TESTFUNCTION( int );
LI_TESTFUNCTION( std::string );
使用VC ++ 2k8&amp; g ++ 4.3.4静态链接LibraryInclude.o