【问题标题】:Template Metaprogramming: Problems with Partial Specialization模板元编程:部分专业化的问题
【发布时间】:2020-08-07 06:34:16
【问题描述】:

我正在尝试探索模板的部分专业化以构建特征系统。不幸的是,我无法让全部工作正常进行。我创建了最简单的模型来展示什么不起作用。我什至不清楚我是否正在尝试不受支持的东西(实际上我看到了相同性质的例子,但细节是魔鬼)。

我只是在创建一个小示例,其中我有两个枚举,并希望根据两者的组合以不同的方式创建一个字符串。当然,这只是一个演示问题的虚拟示例,在这种情况下,同样的事情可以通过许多其他方式来完成。

#ifndef TESTTRAITS_H_
#define TESTTRAITS_H_

#include <string>

using namespace std;

enum MovementType {
    WALKS = 0, SWIMS = 1
};

enum AnimalType {
    DOG = 0, CAT = 1, DOLPHIN = 2
};

template<AnimalType A, MovementType B>
struct movementAnimal {
    static const string quality;
};

template<AnimalType A>
struct movementAnimal<A,WALKS> {
    static const string quality;
};

template<AnimalType A>
struct movementAnimal<A,SWIMS> {
    static const string quality;
};

#endif /* TESTTRAITS_H_ */

现在我写静态变量的赋值

#include "TestTraits.h"

template<>
const string movementAnimal<DOLPHIN, WALKS>::quality = "Not capable";

template<>
const string movementAnimal<DOLPHIN, SWIMS>::quality = "Excellent";

template<AnimalType A>
const string movementAnimal<A, SWIMS>::quality = "Decent";

template<AnimalType A>
const string movementAnimal<A, WALKS>::quality = "Very Well";

还有一个小的 main 函数

#include <iostream>
using namespace std;
#include "TestTraits.h"

int main() {
    cout << movementAnimal<DOLPHIN,WALKS>::quality  << endl;
    cout << movementAnimal<DOG,WALKS>::quality  << endl;
    return 0;
}

如果我编译我得到错误:

/src/TestProject.cpp:15: 未定义对 `movementAnimal::quality[abi:cxx11]' 的引用 collect2: 错误: ld 返回 1 个退出状态>

如果我删除对 motionAnimal::quality 的引用,那么它会完美编译。

我知道它没有消化部分模板规范

template<AnimalType A>
const string movementAnimal<A, WALKS>::quality = "Very Well";

我不知道为什么以及是否有可能使该模式起作用。

【问题讨论】:

标签: c++ templates template-meta-programming


【解决方案1】:

如我所见,您将这些定义放入单独的文件中。模板类的定义在TestTraits.h,但静态常量的定义在其他地方。主 CPP 文件仅包含 TestTraits.h。这听起来应该是一个不错的决定,但在模板世界中却行不通。

所以,您已经定义了枚举和模板/部分特化。您的主 cpp 模块会看到这些定义。好的。编译器在此处实例化walking dog 时就知道模板类:

cout << movementAnimal<DOG,WALKS>::quality  << endl;

编译器是否看到静态常量的定义?如果没有,那这样的代码就没用了:

template<AnimalType A>
const string movementAnimal<A, WALKS>::quality = "Very Well";

当编译器看到上面的代码时,它无法知道您将使用的A 的所有值。所以每当你决定DOGWALKS的时候,这个实例化点就会看到const string movementAnimal&lt;A, WALKS&gt;::quality的定义;

解决方案是确保主函数的代码既知道模板类的定义,也知道静态常量的定义。

有两种解决方案。首先是将所有内容放入一个头文件或包含来自 cpp 文件的两个文件。不要忘记同时包含两者。

第二种解决方案是在代码中的某处显式实例化某些类:

template class movementAnimal<DOG, WALKS>;

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多