C++ 具有不使用模板的函数的模板类
为了减少遗传,我在跳圈 我读到一个类似的问题。它显示了如何使用基类解决问题。我试图摆脱继承,所以我在寻找一些不同的东西——更多的是沿着注释的路线 我创建并编译了一个专门的模板类(C++ 具有不使用模板的函数的模板类,c++,templates,static-libraries,C++,Templates,Static Libraries,为了减少遗传,我在跳圈 我读到一个类似的问题。它显示了如何使用基类解决问题。我试图摆脱继承,所以我在寻找一些不同的东西——更多的是沿着注释的路线 我创建并编译了一个专门的模板类(normal)。需要模板的方法位于标头(Mixer.hpp)中。不需要模板的方法位于cpp文件(Mixer.cpp)中。当编译到静态库中时,cpp部分仅编译为一个专门化(Mixer)。编译器当时不知道(awsome)。将生成的静态库导入另一个项目并尝试创建不同的泛型(awsome)类会导致链接器错误,因为库显然不包含该方
normal
)。需要模板的方法位于标头(Mixer.hpp
)中。不需要模板的方法位于cpp文件(Mixer.cpp
)中。当编译到静态库中时,cpp部分仅编译为一个专门化(Mixer
)。编译器当时不知道(awsome
)。将生成的静态库导入另一个项目并尝试创建不同的泛型(awsome
)类会导致链接器错误,因为库显然不包含该方法标识符(Mixer::noTemplateInvolved
)。但是,正常实现的代码与任何其他实现一样好,因此实际上链接器可以链接到其他模板版本的现有源(Mixer::noTemplateInvolved
)。编译器所要做的就是为链接器适当地标记它
以下是导致链接器错误的源代码:
//Target compiled to Provider.lib
//Mixer.hpp
#pragma once
#include <iostream>
using namespace std;
struct normal { static void log() { cout << "normal\n"; } };
template<typename output = normal>
class Mixer
{
public:
void callingTemplate();
void noTemplateInvolved();
};
template<typename output>
void Mixer<output>::callingTemplate() { output::log(); }
//Mixer.cpp
#include "Mixer.hpp"
void Mixer<>::noTemplateInvolved()
{
cout << "noTemplateInvolved\n";
}
//Target Compiled to User.exe
//This target imports Provider.lib
#include <Provider\Mixer.hpp>
#pragma comment(lib, "Provider.lib")
struct awsome { static void log() { cout << "awsome\n"; } };
int main()
{
Mixer<> n;
n.callingTemplate();
n.noTemplateInvolved();
Mixer<awsome> a;
a.callingTemplate();
a.noTemplateInvolved(); //linker error here
return 0;
}
//目标编译为Provider.lib
//混频器
#布拉格语一次
#包括
使用名称空间std;
struct normal{static void log(){cout答案是注释中建议的基类。我想要基类的原因之一是我不想重构。使用基类重构实际上非常简单
将original
类重命名为original\u base
。
继承自original\u template
继承自original\u base
。确保复制构造函数并将所有参数传递给基类。
使用original=original_template的语句确保还不需要修改其他源代码
应用于上述示例,我最终做了如下操作:
//Target compiled to Provider.lib
//Mixer.hpp
#pragma once
#include <iostream>
using namespace std;
struct normal { static void log() { cout << "normal\n"; } };
class Mixer_Base
{
private:
int mixcount;
public:
Mixer_Base(int count);
void noTemplateInvolved();
};
template<typename output = normal>
class Mixer_tempalte : public Mixer_Base
{
public:
Mixer_tempalte(int count) : Mixer_Base(count)
{}
void callingTemplate();
};
template<typename output>
void Mixer_tempalte<output>::callingTemplate()
{
output::log();
}
using Mixer = Mixer_tempalte<>;
//Mixer.cpp
#include "Mixer.hpp"
void Mixer_Base::noTemplateInvolved()
{
cout << "noTemplateInvolved\n";
}
Mixer_Base::Mixer_Base(int count) : mixcount(count)
{}
//Target Compiled to User.exe
//This target imports Provider.lib
#include <Provider\Mixer.hpp>
#pragma comment(lib, "Provider.lib")
struct awsome { static void log() { cout << "awsome\n"; } };
int main()
{
Mixer n(4);
n.callingTemplate();
n.noTemplateInvolved();
Mixer_tempalte<awsome> a(3);
a.callingTemplate();
a.noTemplateInvolved();
return 0;
}
//目标编译为Provider.lib
//混频器
#布拉格语一次
#包括
使用名称空间std;
结构正常{静态无效日志(){如果它与模板无关,为什么它是一个成员,而且是一个非静态的呢?你可以将它作为一个单独的、非模板的非成员函数来实现,也许只有一个成员存根转发给它-你必须提供存根的定义,但它将只是一行最有可能是内联的。这是不是你在寻找什么?不管怎样,我不知道你为什么不想选择非依赖的基类解决方案;也许在问题中解释这个决定会让你的需求更清楚。你可以使用显式模板实例化。为什么你不想将非模板函数移到基类?它没有开销这种情况。最终目标是重构。如果我可以在标题中注释某些内容,我就不必触及实现。如果没有其他内容,这对我来说是有教育意义的。在本例中,显式实例化不起作用-库是在知道“struct awsome”之前编译的。我将尝试使用extern关键字,尽管我认为它是不受欢迎的在我的实际生产代码中,我开始使用基类,但是我有另一个想法,我将很快实现,看看这是否能让我更接近注释表单。