模板 class 具有不使用模板的函数

template class with functions that do not use the template

我正在努力减少继承。

我看过一个类似的问题here。它显示了如何使用基础 class 解决问题。我试图松散继承,所以我正在寻找不同的东西——更多的是注释。

我创建并编译了一个模板 class,具有一个专业化 (normal)。需要模板的方法在 header (Mixer.hpp) 中。不需要模板的方法在cpp文件中(Mixer.cpp)。当编译成静态库时,cpp 部分只被编译为一个专业化 (Mixer<normal>)。编译器当时不知道 (awsome)。将生成的静态库导入另一个项目并尝试创建不同的泛型 (awsome) class 会导致 linker 错误,因为显然该库不包含该方法标识符 (Mixer<awesome>::noTemplateInvolved).然而,正常实现的代码与任何代码一样好,所以 linker 可以 link 到其他模板版本 (Mixer<?dontcare?>::noTemplateInvolved) 的现有源代码。编译器所要做的就是为 linker.

适当地标记它。

这是导致 linker 错误的源代码:

//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;
}

class Mixer<awsome> 可以 link 方法 callingTemplate 因为它的定义在 header 中并且编译器创建该函数。在 User.exe 编译时,noTemplateInvolved 的定义对编译器是隐藏的。编译器无法创建该方法,linking 必须失败。

我知道三种解决方案。

我正在寻找另一种解决方案。 noTemplateInvolved 的 body 真的和模板没有关系。我想在 header 中注释该方法。我希望编译器知道它应该始终使用相同的基本实现,而不管模板如何。

这可能吗?

编辑:在开头对那个无聊的段落做了一点注释。

答案原来是评论中建议的基础class。我想要 base class 的原因之一是我不想重构。使用基class重构其实很简单。

original class 重命名为 original_base。 继承自 original_template 继承自 original_base。确保复制构造函数并将所有参数传递给基 class。 语句 using original = original_template<your default case here> 确保还没有其他源代码需要修改。

应用到上面的例子我最终做了这样的事情:

//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;
}

在某种程度上,注释感觉就像基础 class 感觉一样。基础 class 中的所有内容现在都按照我想要的方式进行注释,尽管这不会减少继承。