簡體   English   中英

來自單獨文件的模板函數的前向聲明

[英]Forward declaration of a template function from a seperate file

其他.cpp

#include <iostream>
#include <string>
using std::cout;

template <typename T>
std::ostream & cprint(T &t,  std::string msg = "Container", std::ostream & stream = cout){
    stream << msg << "\t{ ";
    for(typename T::iterator it = t.begin(); it != t.end(); it++)
        stream << *it << " ";
    stream << "}\n";

    return stream;
}

我在一個單獨的文件中有一個模板函數。 我正在嘗試在main.cpp文件中轉發聲明它。

extern template std::ostream & cprint<std::vector<int>>
(T &t,  std::string msg = "Container", std::ostream & stream = cout);

我已經嘗試了上面的方法,但它對我不起作用。

編輯:假設 other.cpp 具有如下基本功能,

template <typename T>
void func(T x){
    cout << x << endl;
}

如何在 main.cpp 中實例化這個函數?

請記住,您要問的是(通常)不是使用模板的正確方法。

您應該做的是在標頭中聲明您的模板並擺脫extern聲明和顯式專業化。

將模板放入.cpp通常不是很方便,因為它們要求您在同一個.cpp指定您希望它們適用的所有類型。

但是,另一方面,它提高了編譯速度並且生成的二進制文件有很小的可能性會更小。


如何修復您的代碼:

我對您的代碼進行了一些更改以使其正常工作。

我也做了一些小的改進。 如果您發現它們令人困惑,請在評論中詢問。

// 1.cpp
#include <iostream>
#include <string>
#include <vector>

template <typename T>
std::ostream &cprint(const T &t, std::string msg = "Container", std::ostream &stream = std::cout)
{
    stream << msg << " { ";
    for(typename T::const_iterator it = t.cbegin(); it != t.cend(); it++)
        stream << *it << " ";
    stream << "}\n";
    return stream;
}

template std::ostream &cprint(const std::vector<int> &, std::string, std::ostream &);

// 2.cpp
#include <string>
#include <iostream>
#include <vector>

template <typename T> std::ostream &cprint(const T &, std::string = "Container", std::ostream & = std::cout);

int main()
{
    std::vector<int> v{1,2,3};
    cprint(v);
}

重要部分如下:

  • 顯式實例化。 它必須與模板定義位於同一文件中。
    template std::ostream &cprint(const std::vector<int> &, std::string, std::ostream &);

  • 宣言。 它必須位於您要使用模板的文件中。 template <typename T> std::ostream &cprint(const T &, std::string = "Container", std::ostream & = std::cout);

請注意,如果編譯器無法推斷它們,您可以在顯式實例化和 extern 聲明中手動指定模板參數。


用編輯成問題的虛擬模板做同樣的事情留給讀者作為練習。

除了這個,你也應該閱讀: 使用EXTERN模板(C ++ 11)

要使用extern延遲實例化,您必須完全匹配函數簽名,因此除非T被定義為std::vector<int>或其別名 - 與您的模板聲明匹配,否則下面將不起作用。:

extern template std::ostream & cprint<std::vector<int>>
(T &t,  std::string msg = "Container", std::ostream & stream = cout);

修理,

extern template std::ostream& cprint<std::vector<int>>
(std::vector<int>&, std::string msg = "Container", std::ostream & stream = cout);

這里

更具體地說,

Header.hpp文件中,我有它的聲明和它的延期:

template <typename T>
std::ostream & cprint(T &t,  std::string msg = "Container", std::ostream & stream = cout){
    stream << msg << "\t{ ";
    for(typename T::iterator it = t.begin(); it != t.end(); it++)
        stream << *it << " ";
    stream << "}\n";

    return stream;
}

//defer instantiation
extern template std::ostream& cprint<std::vector<int>>
(std::vector<int>&, std::string msg = "Container", std::ostream & stream = cout);

現在,main.cpp文件中,我有:

int main(){
    std::vector<int> v{1, 2, 3, 4, 5};
    cprint(v);
}

Header.cpp文件中,我有它的實例化:

template std::ostream& cprint<std::vector<int>>
(std::vector<int>&, std::string msg = "Container", std::ostream & stream = cout);

這里所見

======================

編輯:關於您最近的編輯:

編輯:假設 other.cpp 具有如下基本功能,

 template <typename T> void func(T x){ cout << x << endl; }

如何在 main.cpp 中實例化這個函數?

如果翻譯單元main.cpp看到函數模板func的聲明(來自包含的頭文件,或者您(重新(轉發))在main.cpp 中聲明它,它將編譯為調用函數模板專業化1 ,但鏈接器將無法找到函數模板特化,除非它看到在(另一個)翻譯單元中實例化的函數模板特化的定義。


注意:“函數模板特化”是從函數模板實例化的函數。 temp.fct/1

暫無
暫無

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

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