簡體   English   中英

C ++類模板專業化

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM