[英]C++ Class Template Specialization
我是C ++編程的新手,在執行單獨的編譯時遇到了似乎無法解決的問題。 我正在嘗試對我的類tokenize
進行專門tokenize
,以為特定類型( istream
)添加一個dtor。 我有以下幾點:
#ifndef __TOKENIZER_H__
#define __TOKENIZER_H__
#include <fstream>
#include <string>
template <class T>
class base {
// ... some methods/member variables.
};
template <class T>
class tokenizer : public base<T> {
public:
tokenizer(T &in);
};
template <>
class tokenizer<std::ifstream> : public base<std::ifstream> {
public:
tokenizer(std::ifstream &in);
~tokenizer();
};
#endif
...和:
#include "tokenizer.h"
#include <fstream>
#include <iostream>
#include <locale>
using std::ifstream;
using std::istream;
using std::string;
// [BASE]
// ... code for those functions.
// [TOKENIZER]
// See header file.
template <class T>
tokenizer<T>::tokenizer(T &in) : base<T>(in) { }
// See header file.
template <>
tokenizer<ifstream>::tokenizer(ifstream &in) : base<ifstream>(in) { }
// See header file.
template <>
tokenizer<ifstream>::~tokenizer() {
delete &(base<ifstream>::in);
}
// Intantiating template classes (separate compilation).
template class base<std::ifstream>;
template class base<std::istream>;
template class tokenizer<std::ifstream>;
template class tokenizer<std::istream>;
...但是我得到以下錯誤:
tokenizer.cc:62: error: template-id ‘tokenizer<>’ for ‘tokenizer<std::basic_ifstream<char, std::char_traits<char> > >::tokenizer(std::ifstream&)’ does not match any template declaration
tokenizer.cc:66: error: template-id ‘tokenizer<>’ for ‘tokenizer<std::basic_ifstream<char, std::char_traits<char> > >::~tokenizer()’ does not match any template declaration
我正在使用g ++進行編譯。 如果有人可以指出我所缺少的內容以及可能的解釋,那就太好了。 我很困惑模板如何與單獨的編譯(defns / decl分開)一起工作。
[temp.expl.spec] / 5狀態:
顯式專門化的類模板的成員以與普通類的成員相同的方式定義,而不使用
template<>
語法。 當定義顯式專門的成員類的成員時,也是如此。 但是,template<>
用於定義專門化為類模板的顯式專門化成員類模板的成員。
它還提供了以下示例(我僅引用一些摘錄):
template<class T> struct A { template<class U> struct C { }; }; template<> struct A<int> { void f(int); }; // template<> not used for a member of an // explicitly specialized class template void A<int>::f(int) { /∗ ... ∗/ } template<> template<class U> struct A<char>::C { void f(); }; // template<> is used when defining a member of an explicitly // specialized member class template specialized as a class template template<> template<class U> void A<char>::C<U>::f() { /∗ ... ∗/ }
據我所知,一旦您明確地專門化了一個類模板,就創建了一個“普通類”。 顯然,它不再是模板(您無法通過專業化創建類),而是名稱中帶有一些<..>
的類型。
在您的情況下,這僅意味着先忽略template<>
// See header file. //template <> tokenizer<ifstream>::tokenizer(ifstream &in) : base<ifstream>(in) { } // See header file. //template <> tokenizer<ifstream>::~tokenizer() { delete &(base<ifstream>::in); }
關於澄清單獨編譯與模板結合的要求:
當您使用類模板創建對象(例如std::vector<int> v
)或調用函數模板(例如std::sort(begin(v), end(v))
)時,您正在處理模板的專業化 。 std::vector<int>
是類模板std::vector
。
當TU中需要特殊化時,可能有必要從類模板中生成特殊化。 這稱為實例化 。 一個顯式專門化的模板不會被隱式實例化(它已經是專門化的)。 也就是說,您的專業化tokenizer<ifstream>
不必在任何TU中實例化。
由於這些原因,模板本身不能與單獨的編譯一起使用。 但是,您可以使用顯式實例化和專業化明確為模板特提供單獨編制的好處。 例如:
[header.hpp]
template<class T> void foo(T);
extern template void foo<int>(int);
[impl.cpp]
#include "header.hpp"
template<class T> void foo(T) { return T{} };
template void foo<int>(int); // force instantiation
[main.cpp中]
#include "header.hpp"
int main()
{
foo<int>(42); // no instantiation will occur
}
在main.cpp中,我們無法實例化foo
的定義,因為該定義不可用。 我們可以實例化聲明。 還有一個顯式的實例化聲明,可以防止任何隱式的實例化。 在另一個TU(impl.cpp)中,我們通過顯式實例化定義實例化了foo<int>
。 這要求f
的定義存在並實例化該定義。 其余的與普通函數相似:我們有兩個聲明和一個定義。
類似地,對於類模板:如果TU中需要類的定義,則我們需要實例化模板,或者需要具有顯式的特殊化(此處無法使用顯式的實例化定義AFAIK)。 這正是OP的示例。
如果不需要類的定義,我們可以使用類似於PIMPL方法的東西:
[header.hpp]
template<class T>
class foobar;
struct s
{
foobar<int>* p;
void f();
}
[impl.cpp]
#include "header.hpp"
template<class T> class foobar { int i; }
void s::f() { p = new foobar{42}; }
[main.cpp中]
int main()
{
s obj;
obj.f();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.