我正在試驗 C 20 以更好地理解它們在實踐中的作業方式。我了解了module :private可用于將介面與實作分開的片段,同時將兩者保存在同一個檔案中。這似乎適用于標準函式,但不適用于模板函式。
我有以下檔案:
// File "main.cpp"
#include <iostream>
import mymodule;
int main()
{
std::cout << "greeting(): " << mymodule::greetings() << std::endl;
int x = 1;
int y = 2;
std::cout << "add(x, y): " << mymodule::add(x, y) << std::endl;
}
// File "mymodule.ixx"
module;
#include <string>
// declare interface
export module mymodule;
export namespace mymodule {
template<typename T>
T add(T x, T y);
std::string greetings();
}
// implement interface
module :private;
std::string mymodule::greetings() {
return "hello";
}
template<typename T>
T mymodule::add(T x, T y) {
return x y;
}
并獲得編譯器警告和聯結器錯誤(使用 Visual Studio 2022、MSVC):
Rebuild started...
1>------ Rebuild All started: Project: PlayingWithModules, Configuration: Debug x64 ------
1>Scanning sources for module dependencies...
1>mymodule.ixx
1>Compiling...
1>mymodule.ixx
1>C:\Users\Sam\Development\Cpp\Sandbox\PlayingWithModules\mymodule.ixx(29,13): warning C5226: 'mymodule::add': exported template defined in private module fragment has no reachable instantiation
1>main.cpp
1>main.obj : error LNK2019: unresolved external symbol "int __cdecl mymodule::add<int>(int,int)" (??$add@H@mymodule@@YAHHH@Z::<!mymodule>) referenced in function main
1>C:\Users\Sam\Development\Cpp\Sandbox\x64\Debug\PlayingWithModules.exe : fatal error LNK1120: 1 unresolved externals
1>Done building project "PlayingWithModules.vcxproj" -- FAILED.
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
我的理解是這mymodule::greetings()很好,但mymodule::add(x, y)不是因為mymodule::<int, int>(x, y)編譯器看不到函式呼叫,導致沒有<int, int>生成任何函式。
如果我改為將模板函式作為介面的一部分來實作:
module;
#include <string>
// declare interface
export module mymodule;
export namespace mymodule {
template<typename T>
T add(T x, T y) {
return x y;
}
std::string greetings();
}
// implement interface
module :private;
std::string mymodule::greetings() {
return "hello";
}
然后一切都編譯并按預期作業。
是否可以module :private與函式模板一起使用,如果是,如何使用?或者模板函式是否應該始終作為介面的一部分來實作?我無法在網上找到有關模塊背景關系中模板使用的詳細資訊,也找不到對我收到的編譯器警告的參考。
uj5u.com熱心網友回復:
模塊不會改變C 的本質,只會改變您訪問不同組件的方式。
C 的一部分特性是,為了讓翻譯單元使用模板,該翻譯單元必須能夠訪問該模板的定義。模塊不會改變這一點。
私有模塊片段專門包含不屬于模塊介面的內容。這就是它們的全部意義所在:能夠將不屬于介面的內容粘貼到模塊檔案中。
因此,私有模塊片段只能包含您將放入傳統 .cpp 檔案的內容。事實上,這就是它們存在的原因:這樣(對于短模塊)您可以將所有常用的 .cpp 內容放在一個檔案中,而不會影響模塊生成的內容。
uj5u.com熱心網友回復:
根據cppreference,私有模塊片段似乎是一個未記錄的功能,旨在用于該語言的未來擴展。另請注意,對于任何編譯器,模塊都沒有完全實作,因此您會發現可以使用 clang 但會中斷 msvc 等的東西。
但是,如果我正確理解了您的問題,那么您真的很關心在一個檔案中包含的內容,您可以通過在宣告和定義之間沒有任何區別來做到這一點:
// File "mymodule.ixx"
module;
#include <string>
// declare interface
export module mymodule;
export namespace mymodule
{
template<typename T>
T add(T x, T y) {
return x y;
}
std::string greetings() {
return "hello";
}
}
筆記
模塊正在為新的 C 時代鋪平道路。我的意思是我們避免區分頭檔案中的宣告和源檔案中的定義,因為我們不需要任何頭檔案。
這將大大簡化語言。
由于私有模塊片段似乎是一個未記錄的功能,我將建議以下三個選項之一:
- 做如上(即宣告==定義)
- 使用模塊實作單元
- 使用私有模塊片段
我已經在這里回答了如何完成 2) 和 3) 。
由于我無權訪問 msvc-compiler 設定,因此我無法立即檢查如何修復您的示例。請注意,模塊實作很大程度上是編譯器供應商未完成的作業。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/388702.html
標籤:C 模板 C 20 c -modules
