模板类中单个方法的模板特化
始终考虑到包含我的模板类的以下标头至少包含在两个 .CPP
文件中,此代码可以正确编译:
template <class T>
class TClass
{
public:
void doSomething(std::vector<T> * v);
};
template <class T>
void TClass<T>::doSomething(std::vector<T> * v) {
// Do something with a vector of a generic T
}
template <>
inline void TClass<int>::doSomething(std::vector<int> * v) {
// Do something with a vector of int's
}
但请注意专业化方法中的内联。需要避免由于方法被多次定义而导致链接器错误(在VS2008中是LNK2005)。我理解这一点是因为据我所知,完整的模板专业化与简单的方法定义相同。
那么,如何删除该内联
?代码不应在每次使用时重复。我搜索过 Google,阅读了 SO 中的一些问题,并尝试了许多建议的解决方案,但没有成功构建(至少在 VS 2008 中没有)。
谢谢!
Always considering that the following header, containing my templated class, is included in at least two .CPP
files, this code compiles correctly:
template <class T>
class TClass
{
public:
void doSomething(std::vector<T> * v);
};
template <class T>
void TClass<T>::doSomething(std::vector<T> * v) {
// Do something with a vector of a generic T
}
template <>
inline void TClass<int>::doSomething(std::vector<int> * v) {
// Do something with a vector of int's
}
But note the inline in the specialization method. It is required to avoid a linker error (in VS2008 is LNK2005) due to the method being defined more then once. I understand this because AFAIK a full template specialization is the same as a simple method definition.
So, how do I remove that inline
? The code should not be duplicated in every use of it. I've searched Google, read some questions here in SO and tried many of the suggested solutions but none successfully built (at least not in VS 2008).
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
与简单函数一样,您可以使用声明和实现。
放入您的标头声明:
并将实现放入您的 cpp 文件之一:
不要忘记删除内联(我忘记了,并认为此解决方案不起作用:))。
在VC++2005上检查过
As with simple functions you can use declaration and implementation.
Put in your header declaration:
and put implementation into one of your cpp-files:
Don't forget to remove inline (I forgot and thought this solution will not work :) ).
Checked on VC++2005
您需要将专业化定义移至 CPP 文件。
即使函数未声明为模板,也允许对模板类的成员函数进行特化。
You need to move specialization definition to CPP file.
Specialization of member function of template class is allowed even if function is not declared as template.
没有理由删除关键字 inline。
无论如何,它不会改变代码的含义。
There is no reason to remove the keyword inline.
It does not change the meaning of the code in anyway.
如果您出于某种原因想要删除内联,maxim1000 的解决方案是完全有效的。
不过,在您的评论中,您似乎认为 inline 关键字意味着包含所有内容的函数始终被内联,但据我所知,这实际上很大程度上取决于您的编译器优化。
引用自 C++ 常见问题解答
因此,除非您知道该函数实际上会使您的可执行文件膨胀,或者除非您出于其他原因想将其从模板定义标头中删除,否则您实际上可以将其保留在原处而不会造成任何损害
If you want to remove the inline for whatever reason the solution of maxim1000 is perfectly valid.
In your comment, though, it seems you believe that the inline keyword means that the function with all his contents gets always inlined but AFAIK that is actually very much dependent on your compiler optimization.
Quoting from the C++ FAQ
So, unless you know that that function will actually bloat your executable or unless you want to remove it from the template definition header for other reasons, you can actually leave it where it is without any harm
这有点过时了,但我想我会把它留在这里,以防它对其他人有帮助。我在谷歌上搜索模板专业化,这导致我来到这里,虽然@maxim1000的答案是正确的并最终帮助我解决了我的问题,但我认为它还不够清楚。
我的情况与OP的情况有点不同(但我认为足够相似,可以留下这个答案)。基本上,我使用的是第三方库,其中包含定义“状态类型”的所有不同类型的类。这些类型的核心只是枚举,但这些类都继承自公共(抽象)父级,并提供不同的实用函数,例如运算符重载和静态 toString(enum type) 函数。每个状态
enum
彼此不同并且互不相关。例如,一个enum
具有字段NORMAL、DEGRADED、INOPERABLE
,另一个具有AVAILBLE、PENDING、MISSING
等。我的软件负责管理不同组件的不同类型的状态。我想对这些 enum 类使用 toString 函数,但由于它们是抽象的,我无法直接实例化它们。我本可以扩展我想要使用的每个类,但最终我决定创建一个template
类,其中typename
将是任何具体状态enum
> 我关心。对于这一决定可能会有一些争论,但我觉得这比用我自己的自定义类扩展每个抽象枚举类并实现抽象函数要少得多。当然,在我的代码中,我只是希望能够调用.toString(enum type)
并让它打印该enum
的字符串表示形式。由于所有enum
完全不相关,因此它们每个都有自己的toString
函数,这些函数(经过我了解的一些研究后)必须使用模板专门化来调用。这把我引到了这里。下面是为了使这项工作正常工作我必须做的 MCVE。实际上我的解决方案与@maxim1000 的有点不同。这是
enum
的(大大简化的)头文件。实际上,每个enum
类都是在其自己的文件中定义的。该文件代表作为我正在使用的库的一部分提供给我的头文件:添加此行只是为了将下一个文件分隔到不同的代码块中:
下一个文件
下一个
文件,此输出:
不知道这是否是理想的解决我的问题的解决方案,但它对我有用。现在,无论我最终使用多少种枚举类型,我所要做的就是在 .cpp 文件中为
toString
方法添加几行,然后我就可以使用已经定义的库< code>toString 方法,无需自己实现它,也无需扩展我想要使用的每个enum
类。This is a little OT, but I thought I'd leave this here in case it helps someone else. I was googling about template specialization which led me here, and while @maxim1000's answer is correct and ultimately helped me figure my problems out, I didn't think it was abundantly clear.
My situation is a little different (but similar enough to leave this answer I think) than the OP's. Basically, I'm using a third party library with all different kinds of classes that define "status types". The heart of these types are simply
enum
s, but the classes all inherit from a common (abstract) parent and provide different utility functions, such as operator overloading and astatic toString(enum type)
function. Each statusenum
is different from one another and unrelated. For example, oneenum
has the fieldsNORMAL, DEGRADED, INOPERABLE
, another hasAVAILBLE, PENDING, MISSING
, etc. My software is in charge of managing different types of statuses for different components. It came about that I wanted to utilize thetoString
functions for theseenum
classes, but since they're abstract I couldn't instantiate them directly. I could have extended each class I wanted to use, but ultimately I decided to create atemplate
class, where thetypename
would be whatever concrete statusenum
I cared about. Probably some debate can be had about that decision, but I felt like that was a lot less work than extending each abstractenum
class with a custom one of my own and implementing the abstract functions. And of course in my code, I just wanted to be able to call.toString(enum type)
and have it print the string representation of thatenum
. Since all theenum
s were entirely unrelated, they each had their owntoString
functions that (after some research I learned) had to be called using template specialization. That led me here. Below is an MCVE of what I had to do in order to make this work correctly. And actually my solution was a bit different than @maxim1000's.This is a (greatly simplified) header file for the
enum
s. In reality, eachenum
class was defined in it's own file. This file represents the header files that are supplied to me as part of the library I am using:adding this line just to separate the next file into a different code block:
next file
next file
and this outputs:
No clue if this is the ideal solution to solve my problem, but it worked for me. Now, no matter how many enumeration types I end up using, all I have to do is add a few lines for the
toString
method in the .cpp file, and I can use the libraries already-definedtoString
method without implementing it myself and without extending eachenum
class I want to use.我想补充一点,如果您打算将专门化也保留在头文件中,那么仍然有充分的理由保留
inline
关键字。参考:https://stackoverflow.com/a/4445772/1294184
I'd like to add that there is still a good reason to keep the
inline
keyword there if you intend to leave also the specialization in the header file.Reference: https://stackoverflow.com/a/4445772/1294184