簡體   English   中英

C ++中的extern模板構造函數

[英]extern template constructor in c++

在相當長的一段時間里,我一直在努力將模板函數的實現與定義分開。 的C ++ 0x” extern似乎是一個解決方案,但我不能正確地運用它

我的代碼:

main.cpp

#include <iostream>
#include <string>

#include "lexer.h"

int main(int argc, char const *argv[]) {
    std::string foo("foo");
    new lexer((foo.begin()),(foo.end()));
    return 0;
}

lexer.h

#ifndef lexer_h
#define lexer_h
class lexer {
    public:
    extern template<class InputIterator>
    lexer(InputIterator i, InputIterator end);
};
#endif //lexer_h

lexer.cpp

#include "lexer.h"
template<class InputIterator >
lexer::lexer(InputIterator i, InputIterator end) {
    //make it work
};

使用g++ main.cpp lexer.cpp -std=c++0x 我想稍后使用目標文件。

所以看起來如何固定?

除非您知道用作InputIterator參數的完整類型集,否則定義需要進入頭文件。

僅當您知道所需的全套實例化(參數)時,才可以將模板定義(實現)與聲明分開。 編譯器無法記住在一個.cpp (轉換單元)中使用了哪些實例化,而在另一個.cpp使用代碼來提供它們。

正如Andy提到的那樣,您似乎正在尋找的行為先前已分配給C ++ 03 export關鍵字,該關鍵字很少實現,結果卻沒有預期的有用,現在已從標准中完全刪除。

如果您確實想走這條路(我現在正在寫一個類似的庫!),則extern關鍵字需要超出class {}范圍,並且.cpp文件需要顯式實例化所需的專業化知識。

// header file

class lexer {
    public:
    template<class InputIterator>
    lexer(InputIterator i, InputIterator end);
};

extern template lexer::lexer( foo::iterator, foo::iterator );
extern template lexer::lexer( bar::iterator, bar::iterator );

// source file

template<class InputIterator >
lexer::lexer(InputIterator i, InputIterator end) {
    //make it work
};

template lexer::lexer( foo::iterator, foo::iterator );
template lexer::lexer( bar::iterator, bar::iterator );

它不起作用的原因是,您沒有實例化類模板,也沒有實例化類模板的構造函數:在處理除調用該構造函數的lexer.cpp之外的翻譯單元(即.cpp文件)時,編譯器贏得了無法看到其定義,因此它不會為此發出任何目標代碼; 另一方面,在唯一可以看到其定義的翻譯單元( lexer.cpp )中,您不會調用構造函數,因此,編譯器將不會發出任何目標代碼。

結果,在程序的編譯翻譯單元中沒有構造函數的目標代碼,並且在嘗試創建可執行文件時,鏈接程序將抱怨未解析的對類構造函數的引用

當您知道模板將在另一個翻譯單元中(顯式)實例化時, extern關鍵字用於防止在一個翻譯單元中實例化模板(即使其完整定義是可見的!),從而節省了編譯時間。 有關說明,請參見有關StackOverflow的此問答

根據C ++ 11標准的14.7.2 / 2段:

顯式實例化的語法為:

顯式實例化:extern(opt)模板聲明

顯式實例化有兩種形式:顯式實例定義和顯式實例聲明。 顯式實例化聲明extern關鍵字開頭。

因此,您提供的只是一個聲明。 沒有從鏈接程序獲取未解決的參考錯誤,就無法在.cpp文件中.cpp類模板的成員函數定義,除非您在同一轉換單元(即,通過類模板的顯式實例化)實例化它們。只有一個可以訪問這些定義的對象)。

C ++ 03有一個名為export的關鍵字,它可以執行您想實現的目標,但是在C ++ 11的標准化過程中已將其刪除 ,因為事實證明對於編譯器供應商而言,實現起來太困難了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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