简体   繁体   English

模板元编程:部分专业化的问题

[英]Template Metaprogramming: Problems with Partial Specialization

I am Trying to explore partial specialization of templates in order to build a traits system.我正在尝试探索模板的部分专业化以构建特征系统。 Unfortunately I cannot get the full thing working.不幸的是,我无法让全部工作正常进行。 I created the simplest model to show what does not work.我创建了最简单的 model 来展示什么不起作用。 It is not even clear to me whether I am trying something that is not supported (actually I see around examples of the same nature but the devil is in the details).我什至不清楚我是否正在尝试不受支持的东西(实际上我看到了相同性质的例子,但细节是魔鬼)。

I am just creating a small example in which I have two enums and would like to create a string differently depending on the combination of the two.我只是在创建一个小示例,其中我有两个枚举,并希望根据两者的组合以不同的方式创建一个字符串。 Of course this is just a dummy example to show the problem, the same thing in this case can be done in many other ways.当然,这只是一个展示问题的虚拟示例,在这种情况下,同样的事情可以通过许多其他方式完成。

#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_ */

Now I write the assignment of the static variable现在我写 static 变量的赋值

#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";

And a small main function和小主function

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

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

If I compile I get the error:如果我编译我得到错误:

/src/TestProject.cpp:15: undefined reference to `movementAnimal<(AnimalType)0, (MovementType)0>::quality[abi:cxx11]' collect2: error: ld returned 1 exit status> /src/TestProject.cpp:15: undefined reference to `movementAnimal<(AnimalType)0, (MovementType)0>::quality[abi:cxx11]' collect2: error: ld returned 1 exit status>

If I remove the reference to movementAnimal<DOG,WALKS>::quality then it compiles perfectly.如果我删除对 motionAnimal<DOG,WALKS>::quality 的引用,那么它可以完美编译。

I get that it is not digesting the partial template specification我知道它没有消化部分模板规范

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

I do not know why and whether it is possible to have the pattern working.我不知道为什么以及是否有可能使该模式起作用。

As I can see, you put these definitions into separate files.如我所见,您将这些定义放入单独的文件中。 The definition of the template classes is in TestTraits.h , but the definition of the static consts is somewhere else.模板类的定义在TestTraits.h中,但 static 常量的定义在其他地方。 The main CPP file includes just the TestTraits.h .主 CPP 文件仅包含TestTraits.h That should sound like a good decision, but that doesn't work in the world of templates.这听起来应该是一个不错的决定,但在模板的世界里这行不通。

So, you have defined the enums and templates/partial specializations.因此,您已经定义了枚举和模板/部分特化。 Your main cpp module sees these definitions.您的主 cpp 模块会看到这些定义。 Good.好的。 The compiler knows the template classes when it instantiates the walking dog here:编译器在此处实例化walking dog 时知道模板类:

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

Does the compiler see the definition of the static const?编译器是否看到 static const 的定义? If it doesn't, the code like that is useless:如果没有,那么这样的代码是无用的:

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

When the compiler sees the code above it cannot know all the values of A that you would use.当编译器看到上面的代码时,它无法知道您将使用的A所有值。 So whenever you decide that the DOG WALKS , this instantiation point shall see the definition of const string movementAnimal<A, WALKS>::quality ;因此,每当您决定DOG WALKS时,此实例化点将看到const string movementAnimal<A, WALKS>::quality的定义;

The solution is to ensure that the code from main function knows both definitions of template classes and the definitions of static consts.解决方案是确保来自主 function 的代码知道模板类的定义和 static 常量的定义。

There are two solutions.有两种解决方案。 First is to put everything into one header file or to include both files from cpp file.首先是将所有内容放入一个 header 文件或包含来自 cpp 文件的两个文件。 Don't forget to include both.不要忘记包括两者。

The second solution is to have an explicit instantiation of some classes somewhere in your code:第二种解决方案是在代码中的某处显式实例化某些类:

template class movementAnimal<DOG, WALKS>;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM