[問題] 如何強迫struct使用者另外額外賦值?

看板C_and_CPP (C/C++)作者 (梅梅)時間7月前 (2024/04/09 05:19), 7月前編輯推噓8(8029)
留言37則, 7人參與, 5月前最新討論串1/1
完整標題:如何強迫struct使用者在使用copy assignment時,另外對其他某值另外賦值? 開發平台(Platform): (Ex: Win10, Linux, ...) Mac 編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出) clang 14 額外使用到的函數庫(Library Used): (Ex: OpenGL, ...) X 問題(Question): 想請問各位C/CXX先進,我有個需求就是我有一個MyUniquePtr 繼承自unique_ptr,還會有 其他一般的struct包含了這個MyUniquePtr。那我在過程中我會有copy assignment的行為, 我只想要他copy那些一般的Plain Old Data,那個MyUniquePtr務必要求用的人另外對MyUni quePtr賦值。 想請問我有無辦法用一些clang語法,包含preprocessing,在compile階段就發現使用者是 否有另外對MyUniquePtr賦值?我有一些想法但不知道是否可行 給MyUniquePtr的copy assignment overload中,標記為deprecated 1. 假如使用者有MyUniquePtr賦值,那他可標記一些東西,例如#define,或是某些flag? 這樣可以繞過這個deprecated(或搭配-Werror=deprecated-declarations?) 2. 假如使用者有額外賦值,他就可以用#pragma clang diagnostic ignored "-Wdeprecate d-declarations"把他那賦值的包起來來silence error,但這deprecated是在別的header, 包在這邊看起來沒什麼用 想請問各位有什麼其他方法可以做到嗎,簡單說就是如果使用者沒有另外賦值,編譯就報錯 。如果有另外賦值,那就沒事。謝謝指教 餵入的資料(Input): MyStruct s1; MyStruct s2; 1. s1 = s2; 2. s1 = s2; s1.p_char = new char(100); 預期的正確結果(Expected Output): 1. 編譯失敗 2. 可編譯成功 錯誤結果(Wrong Output): 程式碼(Code):(請善用置底文網頁, 記得排版,禁止使用圖檔) https://godbolt.org/z/3M5KveYWa 圖片供手機使用者方便閱讀 https://imgur.com/bXyms0J
補充說明(Supplement): 只能用到c++11 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 174.160.86.171 (美國) ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1712611149.A.F90.html ※ 編輯: mmmmei (174.160.86.171 美國), 04/09/2024 05:23:33

04/09 07:37, 7月前 , 1F
這樣設計的意義是什麼
04/09 07:37, 1F
我是想說這樣比較直覺?就是一個=比較有那種右邊POD都要賦值給左邊的感覺。

04/09 07:41, 7月前 , 2F
要這樣做就用setXX()來取代copy assignment 就好了
04/09 07:41, 2F

04/09 07:42, 7月前 , 3F
copy assignment 直接delete
04/09 07:42, 3F
我有想過這,但如果之後myStruct又多了數個MyUniquePtr的話,那這個setXX介面要頻繁的 更改增加更多參數。所以在想有沒有辦法能把uniquePtr賦值的部分交給用的人來做 ※ 編輯: mmmmei (174.160.86.171 美國), 04/09/2024 09:52:30

04/09 13:27, 7月前 , 4F
只能copy不能move 那為何要unique_ptr
04/09 13:27, 4F
我不太懂這句話意思,是指為什麼不用shared_ptr還是指不用傳統指針嗎? 我也不太懂只能copy不能move這個結論哪裡來的,能麻煩細說一下嗎?感謝 ※ 編輯: mmmmei (174.160.86.171 美國), 04/09/2024 14:43:20

04/09 15:12, 7月前 , 5F
operator的語意要越明確越好,不要有做一半的
04/09 15:12, 5F

04/09 15:33, 7月前 , 6F
copy就copy,move就move。做一半只是變得更難維護而已
04/09 15:33, 6F
嗯嗯合理,我的需求看來只是要copy POD而已,uniq_ptr不動,這樣用opeator看來不恰當

04/09 19:16, 7月前 , 7F
unique_ptr 不允許 copy,因為不能有多個擁有者
04/09 19:16, 7F

04/09 19:17, 7月前 , 8F
所以你在一個允許copy的struct裡面放unique_ptr
04/09 19:17, 8F

04/09 19:17, 7月前 , 9F
本身就非常違和
04/09 19:17, 9F
了解了解,那這opeator看來就不該出現可用

04/10 00:07, 7月前 , 10F
你的設計讓人困惑的點在於,所有的東西你都只要半套而
04/10 00:07, 10F

04/10 00:07, 7月前 , 11F
已,你想要pod style,但你塞unique_ptr的那一刻他就不
04/10 00:07, 11F

04/10 00:07, 7月前 , 12F
是pod了,你用unique_ptr卻不打算按move跟ownership的
04/10 00:07, 12F

04/10 00:07, 7月前 , 13F
規則來玩,你想要做copy assignment,但你在做的事也只
04/10 00:07, 13F

04/10 00:07, 7月前 , 14F
有一部分的copy,剩下來那一部分要不要copy要使用者自
04/10 00:07, 14F

04/10 00:07, 7月前 , 15F
己去弄,老實說,這應該沒有比較直覺XD
04/10 00:07, 15F
確實是都半套而已,好吧看來確實只是我一廂情願而已,之後別人用的話應該反而覺得很不 直覺

04/10 02:02, 7月前 , 16F
為什麼要user給值?你不能直接deep copy就好?是說如果
04/10 02:02, 16F
Emmm因為其實只想要copy其他POD,unq_ptr是會另外操作

04/10 02:02, 7月前 , 17F
要能copy為什麼不乾脆不要用unique_ptr直接用aggregate
04/10 02:02, 17F

04/10 02:02, 7月前 , 18F
type
04/10 02:02, 18F

04/10 02:03, 7月前 , 19F
比如強迫該type一定要trivial copyable
04/10 02:03, 19F

04/10 02:05, 7月前 , 20F
我覺得繼承unique_ptr這個設計也有點怪,你想要可以copy
04/10 02:05, 20F

04/10 02:05, 7月前 , 21F
的uniq_ptr用意到底是什麼...refactor舊code?
04/10 02:05, 21F
其實也不是非要copy,只是希望在外面用的時候(例子裡的s1=s2)時,可以直接用operato r=(我個人"覺得"看起來比較直覺啦) 感謝各位提供意見,看來我原本這想法本身是很反語言設計邏輯的,總之我的UniquePtr就 是該繼續delete掉copy assignment不該使用對吧? 那現在原帖問題變成: 有什麼比較優雅的方式能夠在MyStruct中,把所有trivially_copy able的POD值都複製過去?(unique_ptr會另外賦值) 因為若另外定義一個function “copyPOD()”,生怕若之後MyStruct有多新的field,會忘 記加在copyPOD裡。 ※ 編輯: mmmmei (17.213.209.49 美國), 04/10/2024 04:56:37

04/10 09:44, 7月前 , 22F
優雅的方式:Reflection?
04/10 09:44, 22F

04/10 09:44, 7月前 , 23F
04/10 09:44, 23F

04/10 09:47, 7月前 , 24F
怕之後少加field的話,可以看一下X macro pattern
04/10 09:47, 24F
嗯嗯謝謝關鍵字,我也有試了下確實可行(缺點只是macro又臭又長)

04/10 09:59, 7月前 , 25F
規定所有人把放在trivially copyable的東西統統放MyStru
04/10 09:59, 25F

04/10 09:59, 7月前 , 26F
ct::mPod裡面,複製的時候只複製mPod
04/10 09:59, 26F

04/10 10:00, 7月前 , 27F
很遺憾你不能阻止人亂塞但code review可以定他
04/10 10:00, 27F
嗯嗯謝謝,這個看起來也符合設計邏輯,缺點只是現有那些field都要多加個.mPod.

04/10 23:34, 7月前 , 28F
像樓上講的一樣,你可以把pod的部分包一個struct
04/10 23:34, 28F

04/10 23:35, 7月前 , 29F
然後這裡可以考慮用繼承做:
04/10 23:35, 29F

04/10 23:36, 7月前 , 30F
嗯嗯謝謝,這跟aggregate看起來各有千秋,感覺就是使用時機不太同?但看起來也挺優雅 的

04/11 22:08, 7月前 , 31F
樓上的做法不錯,不過我習慣aggregate
04/11 22:08, 31F
※ 編輯: mmmmei (17.213.209.49 美國), 04/12/2024 05:07:58

06/07 14:22, 5月前 , 32F
你就把 operator=(const MyStruct&) 直接 delete 掉
06/07 14:22, 32F

06/07 14:23, 5月前 , 33F
然後做一個 operator=(const MyStruct::Src&) 來用
06/07 14:23, 33F

06/07 14:24, 5月前 , 34F
再定義一個 MyStruct::Src operator(特殊要求) 來用
06/07 14:24, 34F

06/07 14:26, 5月前 , 35F
這樣 s1 = s2 會編譯錯誤 s1 = s2(new char(100)) 會過
06/07 14:26, 35F

06/07 14:28, 5月前 , 36F
這類作法可以實現你的要求 但我想你還是該想想這樣的設計
06/07 14:28, 36F

06/07 14:29, 5月前 , 37F
是否真的好用 以及是否有其必要
06/07 14:29, 37F
文章代碼(AID): #1c55zD-G (C_and_CPP)
文章代碼(AID): #1c55zD-G (C_and_CPP)