...ãã³ãã¬ãŒããã©ã¡ãŒã¿ã®å€ã«å¿ããŠç°ãªãå
容ã§ãã³ãã¬ãŒãã¯ã©ã¹ãåããæ¹æ³ã¯ïŒ
ãããããããããªãåã«ãC ++ã§åŸãããçµéšãèæ
®ããŠãDèšèªã¯ãæ£ããC ++ããšããŠäœæãããããã«ãªããŸããã æéãçµã€ã«ã€ããŠãDã¯C ++ãããè€éã§è¡šçŸåè±ããªèšèªã«ãªããŸããã ãããŠããã§ã«C ++ã¯Dãã¹ãã€ãå§ããŸãããããšãã°ã if constexpr
ãDããçŽæ¥åçšããŠããif constexpr
ãC ++ 17ã«ç»å ŽããŸããããã®ãããã¿ã€ãã¯D-shny static ifã§ããã
æ®å¿µãªãããC ++ã®if constexpr
ãDã®static if
ãšåãåãæããªãstatic if
ãããã«ã¯ããã€ãã®çç±ããããŸãããC ++ã®if constexpr
ãC + +ã¯ã©ã¹ã ãããã®ã±ãŒã¹ã®1ã€ã«ã€ããŠã話ãããããšæããŸãã
ãã³ãã¬ãŒãã¯ã©ã¹ãäœæããæ¹æ³ã«ã€ããŠèª¬æããŸãããã³ãã¬ãŒãã¯ã©ã¹ã®å
容ïŒã¡ãœããã®æ§æãšã¡ãœããã®ããžãã¯ïŒã¯ããã®ãã³ãã¬ãŒãã¯ã©ã¹ã«æž¡ããããã©ã¡ãŒã¿ãŒã«å¿ããŠå€åããŸãã äŸã¯ãSObjectizerã®æ°ããããŒãžã§ã³ãéçºããçµéšãããå®ç掻ããåãããŠããŸãã
解決ãã¹ã課é¡
ã¡ãã»ãŒãžãªããžã§ã¯ããä¿åããããã®ãã¹ããŒããã€ã³ã¿ãã®è³¢ãããŒãžã§ã³ãäœæããå¿
èŠããããŸãã 次ã®ããã«æžãããšãã§ããŸãïŒ
message_holder_t<my_message> msg{ new my_message{...} }; send(target, msg); send(another_target, msg);
ãã®message_holder_t
ã¯ã©ã¹ã®message_holder_t
isã¯ãèæ
®ãã¹ã3ã€ã®éèŠãªèŠçŽ ãããããšã§ãã
ç¶æ¿ãããã¡ãã»ãŒãžã®çš®é¡ã¯äœã§ããïŒ
message_holder_t
ããã©ã¡ãŒã¿ãŒåããã¡ãã»ãŒãžã®ã¿ã€ãã¯ã2ã€ã®ã°ã«ãŒãã«åããããŸãã æåã®ã°ã«ãŒãã¯ãç¹å¥ãªããŒã¹ã¿ã€ãmessage_t
ãç¶æ¿ããmessage_t
ã§ãã äŸïŒ
struct so5_message final : public so_5::message_t { int a_; std::string b_; std::chrono::milliseconds c_; so5_message(int a, std::string b, std::chrono::milliseconds c) : a_{a}, b_{std::move(b)}, c_{c} {} };
ãã®å Žåãå
éšã®message_holder_tã«ã¯ããã®ã¿ã€ãã®ãªããžã§ã¯ããžã®ãã€ã³ã¿ãŒã®ã¿ãå«ããå¿
èŠããããŸãã åããã€ã³ã¿ãŒãã²ãã¿ãŒã¡ãœããã§è¿ãããå¿
èŠããããŸãã ã€ãŸãã message_t
ã®ç¶æ¿è
ã®å Žåã次ã®ããã«ãªããŸãã
template<typename M> class message_holder_t { intrusive_ptr_t<M> m_msg; public: ... const M * get() const noexcept { return m_msg.get(); } };
2çªç®ã®ã°ã«ãŒãã¯ã message_t
ããç¶æ¿ãããªãä»»æã®ãŠãŒã¶ãŒã¿ã€ãã®message_t
ã§ãã äŸïŒ
struct user_message final { int a_; std::string b_; std::chrono::milliseconds c_; user_message(int a, std::string b, std::chrono::milliseconds c) : a_{a}, b_{std::move(b)}, c_{c} {} };
SObjectizerã®ãããã®ã¿ã€ãã®ã€ã³ã¹ã¿ã³ã¹ã¯ãããèªäœã§ã¯éä¿¡ãããŸããããç¹å¥ãªã©ãããŒuser_type_message_t<M>
ã§å²ãŸããŠããŸãã user_type_message_t<M>
ã©ãããŒã¯ãæ¢ã«message_t
ããç¶æ¿ãmessage_t
ãŸãã ãããã£ãŠããã®ãããªåã®å Žåã message_holder_t
ã¯ãã®äžã«user_type_message_t<M>
ãžã®ãã€ã³ã¿ãŒãå«ãå¿
èŠããããã²ãã¿ãŒã¡ãœããã¯Mãžã®ãã€ã³ã¿ãŒãè¿ãå¿
èŠããããŸãã
template<typename M> class message_holder_t { intrusive_ptr_t<user_type_message_t<M>> m_msg; public: ... const M * get() const noexcept { return std::addressof(m_msg->m_payload); } };
ã¡ãã»ãŒãžã®èæ§ãŸãã¯å¯å€æ§
2çªç®ã®èŠå ã¯ãã¡ãã»ãŒãžãäžå€ããã³å¯å€ã«åå²ããããšã§ãã ã¡ãã»ãŒãžãäžå€ïŒããã³ããã©ã«ãã§ã¯äžå€ïŒã§ããå Žåãgetterã¡ãœããã¯ã¡ãã»ãŒãžãžã®å®æ°ãã€ã³ã¿ãŒãè¿ãå¿
èŠããããŸãã ãŸããå¯å€ã®å Žåãã²ãã¿ãŒã¯éå®æ°ãã€ã³ã¿ãŒãè¿ãå¿
èŠããããŸãã ã€ãŸã 次ã®ãããªãã®ã§ãªããã°ãªããŸããïŒ
message_holder_t<so5_message> msg1{...};
shared_ptr vs unique_ptr
3çªç®ã®èŠå ã¯ãã¹ããŒããã€ã³ã¿ãŒãšããŠã®message_holder_t
ã®åäœã®ããžãã¯ã§ãã ããããããã std::shared_ptr
ããã«æ¯ãèãå¿
èŠããããŸãã åãã¡ãã»ãŒãžã€ã³ã¹ã¿ã³ã¹ãåç
§ããè€æ°ã®message_holdersãæã€ããšãã§ããŸãã ãããŠãäžåºŠstd::unique_ptr
ããã«æ¯ãèãã¯ãã§ãã ã¡ãã»ãŒãžã€ã³ã¹ã¿ã³ã¹ãåç
§ã§ããmessage_holderã€ã³ã¹ã¿ã³ã¹ã¯1ã€ã ãã§ãã
ããã©ã«ãã§ã¯ã message_holder_t
ã®åäœã¯ãã¡ãã»ãŒãžã®å¯å€æ§/äžå€æ§ã«äŸåããå¿
èŠããããŸãã ã€ãŸã äžå€ã®ã¡ãã»ãŒãžã§ã¯ã message_holder_t
ã¯std::shared_ptr
ããã«åäœãã std::unique_ptr
ãããªå¯å€std::unique_ptr
ïŒ
message_holder_t<so5_message> msg1{...}; message_holder_t<so5_message> msg2 = msg;
ãããã人çã¯è€éãªãã®ãªã®ã§ã message_holder_t
åäœãæåã§èšå®ã§ããããã«ããå¿
èŠããããŸãã ããã«ãããunique_ptrã®ããã«åäœããäžå€ã¡ãã»ãŒãžã®message_holderãäœæã§ããŸãã ãããŠãshared_ptrã®ããã«åäœããå¯å€ã¡ãã»ãŒãžã®message_holderãäœæã§ããŸãã
using unique_so5_message = so_5::message_holder_t< so5_message, so_5::message_ownership_t::unique>; unique_so5_message msg1{...}; unique_so5_message msg2 = msg1;
ãããã£ãŠã message_holder_t
ãshared_ptrã®ããã«æ©èœããå Žåãéåžžã®ã³ã³ã¹ãã©ã¯ã¿ãŒãšå²ãåœãŠæŒç®åã®ã»ããïŒã³ããŒãšç§»åã®äž¡æ¹ïŒãå¿
èŠã§ãã ããã«ãå®æ°ã¡ãœããmake_reference
ãå¿
èŠmake_reference
ããã®ã¡ãœããã¯ã message_holder_t
å
ã«æ ŒçŽãããŠãããã€ã³ã¿ãŒã®ã³ããŒãè¿ããŸãã
ãã ãã message_holder_t
ãunique_ptrãšããŠæ©èœããå Žåã¯ãã³ã³ã¹ãã©ã¯ã¿ãšã³ããŒæŒç®åãçŠæ¢ããå¿
èŠããããŸãã make_reference
ã¡ãœããã¯ã message_holder_t
ãªããžã§ã¯ããããã€ã³ã¿ãŒãmake_reference
ããå¿
èŠããããŸãmake_reference
ãåŒã³åºããåŸmake_reference
å
ã®message_holder_t
ã¯ç©ºã®ãŸãŸã«ããŠããå¿
èŠããããŸãã
ãã®ããããã³ãã¬ãŒãã¯ã©ã¹ãäœæããå¿
èŠããããŸãã
template< typename M, message_ownership_t Ownership = message_ownership_t::autodetected> class message_holder_t {...};
ã©ãïŒ
- Mã
message_t
ããç¶æ¿ããããã©ããã«å¿ããŠã intrusive_ptr_t<M>
ãŸãã¯intrusive_ptr<user_type_message_t<M>>
ãå
éšã«æ ŒçŽããå¿
èŠããããŸãã - getterã¡ãœããã¯ãã¡ãã»ãŒãžã®å¯å€æ§/äžå€æ§ã«å¿ããŠã
const M*
ãŸãã¯M*
è¿ãå¿
èŠããããŸãã - ã³ã³ã¹ãã©ã¯ã¿ãšã³ããŒ/移åæŒç®åã®å®å
šãªã»ããããŸãã¯ã³ã³ã¹ãã©ã¯ã¿ãšç§»åæŒç®åã®ã¿ã®ãããããå¿
èŠã§ã
make_reference()
ã¡ãœããã¯ãæ ŒçŽãããŠããintrusive_ptrã®ã³ããŒãè¿ãããintrusive_ptrã®å€ãååŸããŠå
ã®message_holder_t
空ã®ãŸãŸã«ããå¿
èŠããããŸãã æåã®å Žåã make_reference()
ã¯å®æ°ã§ãªããã°ãªããã2çªç®ã®å Žå-éå®æ°ã¡ãœããã§ãã
ãªã¹ãã®æåŸã®2ã€ã®é
ç®ã¯ãæææš©ãã©ã¡ãŒã¿ãŒïŒããã³autodetected
å€ãautodetected
å Žåã®ã¡ãã»ãŒãžã®å¯å€æ§ïŒã«ãã£ãŠæ±ºå®ãããŸãã
決å®æ¹æ³
ãã®ã»ã¯ã·ã§ã³ã§ã¯ãæçµçãªãœãªã¥ãŒã·ã§ã³ãæ§æãããã¹ãŠã®ã³ã³ããŒãã³ããæ€èšããŸãã ããŠãçµæã®ãœãªã¥ãŒã·ã§ã³èªäœã æ°ãæ£ã詳现ããã¹ãŠã¯ãªã¢ãããã³ãŒããã©ã°ã¡ã³ãã衚瀺ãããŸãã 誰ããå®éã®ã³ãŒãã«èå³ããããªãã ããã§ãããèŠãããšãã§ããŸã ã
å
責äºé
以äžã«ç€ºããœãªã¥ãŒã·ã§ã³ã¯ãçŸãçæ³ããŸãã¯ããŒã«ã¢ãã«ã®ãµãããããã®ã§ã¯ãããŸããã ç· ãåãã®ãã¬ãã·ã£ãŒã®äžãçæéã§çºèŠãå®è£
ããã¹ããææžåãããŸããã ããããããã£ãšæéãããã解決çã®æ€çŽ¢ã«ãã£ãšå€ãã®æéãè²»ããããšããã è¥ã çŸä»£ã®C ++éçºè
ã«ãšã£ãŠè³¢æã§ç¥èãè±å¯ãªãããããã³ã³ãã¯ãã§ã·ã³ãã«ã§ç解ãããããã®ã«ãªããŸãã ãããããããèµ·ãã£ããšããããã¯èµ·ãããŸãã...ããã¢ãã¹ããæã€ãªããäžè¬ã«ã
æé ã®ã·ãŒã±ã³ã¹ãšæ¢è£œã®ãã³ãã¬ãŒãããžãã¯
ãã®ãããããã€ãã®ã¡ãœããã®ã»ãããæã€ã¯ã©ã¹ãå¿
èŠã§ãã ãããã®ãããã®å
容ã¯ã©ããããã®ãã®ã§ãªããã°ãªããŸããã ã©ãããïŒ
Dã§ã¯ã static if
ã䜿çšããããŸããŸãªæ¡ä»¶ã«å¿ããŠã¯ã©ã¹ã®ããŸããŸãªéšåãå®çŸ©ã§ããŸãã äžéšã®Rubyã§ã¯ãincludeã¡ãœããã䜿çšããŠã¡ãœãããã¯ã©ã¹ã«ããã¯ã¹ã§ããŸãã ããããç§ãã¡ã¯C ++ã䜿çšããŠããŸããããããŸã§ã®ãšããå¯èœæ§ã¯éåžžã«éãããŠããŸããã¯ã©ã¹å
ã§ã¡ãœãã/å±æ§ãçŽæ¥å®çŸ©ããããåºæ¬ã¯ã©ã¹ããã¡ãœãã/å±æ§ãç¶æ¿ããããšãã§ããŸãã
æ¡ä»¶ã«å¿ããŠã¯ã©ã¹å
ã§ç°ãªãã¡ãœãã/å±æ§ãå®çŸ©ããããšã¯ã§ããŸããã if constexpr
ãstatic if
ãªãif constexpr
C ++ã ãããã£ãŠãç¶æ¿ã®ã¿ãæ®ããŸãã
æŽæ°ããŸããã ã³ã¡ã³ãã§ç€ºåãããŠããããã«ãç§ã¯ããã§ãã£ãšæ³šææ·±ã話ãã¹ãã§ãã C ++ã«ã¯SFINAEããããããSFINAEãä»ããŠã¯ã©ã¹å
ã®åã
ã®ã¡ãœããã®å¯èŠæ§ãæå¹/ç¡å¹ã«ããããšãã§ããŸãïŒã€ãŸãã static if
䌌ãå¹æãå®çŸãstatic if
ïŒã ãããããã®ã¢ãããŒãã«ã¯ãç§ã®æèŠã§ã¯ã2ã€ã®é倧ãªæ¬ ç¹ããããŸãã ãŸãããã®ãããªã¡ãœããã1-2-3ã§ã¯ãªãã4-5以äžã®å ŽåãSFINAEã䜿çšããŠåã¡ãœãããèšèšããã®ã¯é¢åã§ãããããã¯ã³ãŒãã®å¯èªæ§ã«åœ±é¿ããŸãã 第äºã«ãSFINAEã¯ãã¯ã©ã¹å±æ§ïŒãã£ãŒã«ãïŒã®è¿œå /åé€ãæ¯æŽããŸããã
C ++ã§ã¯ã message_holder_t
ãç¶æ¿ããããã€ãã®åºæ¬ã¯ã©ã¹ãå®çŸ©ã§ããŸãã ãŸãã1ã€ãŸãã¯å¥ã®åºæ¬ã¯ã©ã¹ã®éžæã¯ããã³ãã¬ãŒããã©ã¡ãŒã¿ãŒã®å€ã«å¿ããŠã std ::æ¡ä»¶ã䜿çšããŠæ¢ã«è¡ãããŸã ã
ããããã³ãã¯ãåºæ¬ã¯ã©ã¹ã®ã»ããã ãã§ãªããç¶æ¿ã®å°ããªãã§ãŒã³ãå¿
èŠãªããšã§ãã æåã«ãã©ã®ãããªå Žåã§ãå¿
èŠãšãããäžè¬çãªæ©èœã決å®ããã¯ã©ã¹ããããŸãã 次ã¯ããã¹ããŒããã€ã³ã¿ãŒãã®åäœã®ããžãã¯ã決å®ããåºæ¬ã¯ã©ã¹ã§ãã ãããŠãå¿
èŠãªã²ãã¿ãŒã決å®ããã¯ã©ã¹ããããŸãã ãã®é åºã§ãå®è£
ãããã¯ã©ã¹ãæ€èšããŸãã
SObjectizerã«ã¯ãã¡ãã»ãŒãžãã¡ãã»ãŒãžã®å¯å€æ§ããã§ãã¯ããæ段ãšåæ§ã«ãmessage_tããç¶æ¿ããããã©ããã決å®ããæ¢è£œã®ãã³ãã¬ãŒãããžãã¯ãæ¢ã«ãããšããäºå®ã«ãã£ãŠãã¿ã¹ã¯ãåçŽåãããŠããŸã ã ãããã£ãŠãå®è£
ã§ã¯ããã®æ¢è£œã®éæ³ã䜿çšããã ãã§ããã®äœæ¥ã®è©³çŽ°ã«ã€ããŠã¯è©³ãã説æããŸããã
å
±éã®ãã€ã³ã¿ãŒã¹ãã¬ãŒãžããŒã¹
察å¿ããintrusive_ptrãæ ŒçŽããå
±éã®ããŒã¹ã¿ã€ãããå§ããŸãããããŸãã message_holder_t
å®è£
ã®ãããããå¿
èŠãšããã¡ãœããã®å
±éã»ãããæäŸããŸãã
template< typename Payload, typename Envelope > class basic_message_holder_impl_t { protected : intrusive_ptr_t< Envelope > m_msg; public : using payload_type = Payload; using envelope_type = Envelope; basic_message_holder_impl_t() noexcept = default; basic_message_holder_impl_t( intrusive_ptr_t< Envelope > msg ) noexcept : m_msg{ std::move(msg) } {} void reset() noexcept { m_msg.reset(); } [[nodiscard]] bool empty() const noexcept { return static_cast<bool>( m_msg ); } [[nodiscard]] operator bool() const noexcept { return !this->empty(); } [[nodiscard]] bool operator!() const noexcept { return this->empty(); } };
ãã®ãã³ãã¬ãŒãã¯ã©ã¹ã«ã¯2ã€ã®ãã©ã¡ãŒã¿ãŒããããŸãã æåã®ãã€ããŒãã¯ãã²ãã¿ãŒã¡ãœããã䜿çšããã¿ã€ããèšå®ããŸãã äžæ¹ã2çªç®ã®Envelopeã¯ãintrusive_ptrã®ã¿ã€ããèšå®ããŸãã ã¡ãã»ãŒãžã¿ã€ããmessage_t
ããç¶æ¿ãããå Žåããããã®ãã©ã¡ãŒã¿ãŒã¯äž¡æ¹ãšãåãå€ã«ãªããŸãã ãã ããã¡ãã»ãŒãžãmessage_t
ããç¶æ¿ãããŠããªãå Žåãã¡ãã»ãŒãžã¿ã€ãã¯ãã€ããŒããšããŠäœ¿çšããã user_type_message_t<Payload>
ã¯EnvelopeãšããŠuser_type_message_t<Payload>
ããŸãã
åºæ¬çã«ãã®ã¯ã©ã¹ã®å
容ã¯çåãæããããªããšæããŸãã ãã ãã2ã€ã®ç¹ã«æ³šæããŠãã ããã
ãŸãããã€ã³ã¿ãŒèªäœãã€ãŸã ã¯ã©ã¹ç¶æ¿è
ãã¢ã¯ã»ã¹ã§ããããã«ãm_msgå±æ§ã¯protectedã»ã¯ã·ã§ã³ã§å®çŸ©ãããŠããŸãã
第äºã«ããã®ã¯ã©ã¹ã§ã¯ãã³ã³ãã€ã©ãŒèªäœãå¿
èŠãªãã¹ãŠã®ã³ã³ã¹ãã©ã¯ã¿ãŒãšã³ããŒ/移åæŒç®åãçæããŸãã ãã®ã¯ã©ã¹ã®ã¬ãã«ã§ã¯ããŸã äœãçŠæ¢ããŠããŸããã
shared_ptrããã³unique_ptrã®åäœã®åå¥ã®ããŒã¹
ãã®ãããã¡ãã»ãŒãžãžã®ãã€ã³ã¿ãŒãæ ŒçŽããã¯ã©ã¹ããããŸãã ããã§ãçžç¶äººãå®çŸ©ã§ããŸããããã¯shared_ptrãŸãã¯unique_ptrãšããŠåäœããŸãã
shared_ptrã®åäœã®å Žåããå§ããŸãããããªããªãã ããã«æå°ã®ã³ãŒãããããŸãïŒ
template< typename Payload, typename Envelope > class shared_message_holder_impl_t : public basic_message_holder_impl_t<Payload, Envelope> { using direct_base_type = basic_message_holder_impl_t<Payload, Envelope>; public : using direct_base_type::direct_base_type; [[nodiscard]] intrusive_ptr_t< Envelope > make_reference() const noexcept { return this->m_msg; } };
è€éãªããšã¯ãããŸããbasic_message_holder_impl_t
ããç¶æ¿ãããã®ãã¹ãŠã®ã³ã³ã¹ãã©ã¯ã¿ãŒãç¶æ¿ãã make_reference()
åçŽã§éç Žå£çãªå®è£
ãå®çŸ©ããŸãã
unique_ptrã®åäœã®å Žåãã³ãŒãã¯å€§ãããªããŸãããè€éãªãã®ã¯ãããŸããã
template< typename Payload, typename Envelope > class unique_message_holder_impl_t : public basic_message_holder_impl_t<Payload, Envelope> { using direct_base_type = basic_message_holder_impl_t<Payload, Envelope>; public : using direct_base_type::direct_base_type; unique_message_holder_impl_t( const unique_message_holder_impl_t & ) = delete; unique_message_holder_impl_t( unique_message_holder_impl_t && ) = default; unique_message_holder_impl_t & operator=( const unique_message_holder_impl_t & ) = delete; unique_message_holder_impl_t & operator=( unique_message_holder_impl_t && ) = default; [[nodiscard]] intrusive_ptr_t< Envelope > make_reference() noexcept { return { std::move(this->m_msg) }; } };
ç¹°ãè¿ããŸããã basic_message_holder_impl_t
ããç¶æ¿ããå¿
èŠãªã³ã³ã¹ãã©ã¯ã¿ãŒãç¶æ¿ããŸãïŒããã¯ããã©ã«ãã®ã³ã³ã¹ãã©ã¯ã¿ãŒããã³åæåã³ã³ã¹ãã©ã¯ã¿ãŒã§ãïŒã ãããåæã«ãunique_ptrããžãã¯ã«åŸã£ãŠãã³ã³ã¹ãã©ã¯ã¿ãŒãšã³ããŒ/移åæŒç®åãå®çŸ©ããŸããã³ããŒãçŠæ¢ãã移åãå®è£
ããŸãã
ããã«ã¯ç Žå£çãªmake_reference()
ã¡ãœãããããmake_reference()
ã
ããã§ãã¹ãŠã§ãã ãããã®2ã€ã®åºæ¬ã¯ã©ã¹ã®éã®éžæãå®çŸããããã ãã«æ®ããŸã...
shared_ptrãšunique_ptrã®åäœã®éžæ
shared_ptrã®åäœãšunique_ptrã®åäœãéžæããã«ã¯ã次ã®ã¡ã¿é¢æ°ãå¿
èŠã§ãïŒã¡ã¿é¢æ°ã¯ã³ã³ãã€ã«æã«åã§ãæ©èœãããããïŒã
template< typename Msg, message_ownership_t Ownership > struct impl_selector { static_assert( !is_signal<Msg>::value, "Signals can't be used with message_holder" ); using P = typename message_payload_type< Msg >::payload_type; using E = typename message_payload_type< Msg >::envelope_type; using type = std::conditional_t< message_ownership_t::autodetected == Ownership, std::conditional_t< message_mutability_t::immutable_message == message_mutability_traits<Msg>::mutability, shared_message_holder_impl_t<P, E>, unique_message_holder_impl_t<P, E> >, std::conditional_t< message_ownership_t::shared == Ownership, shared_message_holder_impl_t<P, E>, unique_message_holder_impl_t<P, E> > >; };
ãã®ã¡ã¿é¢æ°ã¯ã message_holder_t
ãã©ã¡ãŒã¿ãŒãªã¹ãããäž¡æ¹ã®ãã©ã¡ãŒã¿ãŒãåãå
¥ãããã®çµæïŒã€ãŸãããã¹ããããtype
å®çŸ©ïŒãç¶æ¿å
ã®åããè¿ããŸããã ã€ãŸã shared_message_holder_impl_t
ãŸãã¯unique_message_holder_impl_t
ããããã
impl_selector
ã®å®çŸ©å
ã§ã¯ãäžèšã®éæ³ã®çè·¡ãèŠãããšãã§ããŸãããããã§ã¯èª¬æããŸããã§ããïŒ message_payload_type<Msg>::payload_type
ã message_payload_type<Msg>::envelope_type
ããã³message_mutability_traits<Msg>::mutability
ãããŠãã¡ã¿é¢æ°impl_selector
ã䜿çšããimpl_selector
ãç°¡åã ã£ãã®ã§ãçãååãå®çŸ©ããŸãïŒ
template< typename Msg, message_ownership_t Ownership > using impl_selector_t = typename impl_selector<Msg, Ownership>::type;
ã²ãã¿ãŒã®ããŒã¹
ãã®ããããã§ã«ãã€ã³ã¿ãŒãå«ã¿ããã¹ããŒããã€ã³ã¿ãŒãã®åäœãå®çŸ©ããããŒã¹ãéžæããæ©äŒããããŸãã 次ã«ããã®ããŒã¹ã«ã²ãã¿ãŒã¡ãœãããæäŸããå¿
èŠããããŸãã åçŽãªã¯ã©ã¹ã1ã€å¿
èŠãªçç±ïŒ
template< typename Base, typename Return_Type > class msg_accessors_t : public Base { public : using Base::Base; [[nodiscard]] Return_Type * get() const noexcept { return get_ptr( this->m_msg ); } [[nodiscard]] Return_Type & operator * () const noexcept { return *get(); } [[nodiscard]] Return_Type * operator->() const noexcept { return get(); } };
ããã¯2ã€ã®ãã©ã¡ãŒã¿ãŒã«äŸåãããã³ãã¬ãŒãã¯ã©ã¹ã§ããããããã®æå³ã¯ãŸã£ããç°ãªããŸãã Baseãã©ã¡ãŒã¿ãŒã¯ãäžèšã®impl_selector
ã¡ã¿é¢æ°ã®çµæã§ãã ã€ãŸã Baseãã©ã¡ãŒã¿ãŒãšããŠãç¶æ¿å
ã®åºæ¬ã¯ã©ã¹ãèšå®ãããŸãã
ã³ã³ã¹ãã©ã¯ã¿ãŒãšã³ããŒæŒç®åãçŠæ¢ãããŠããunique_message_holder_impl_t
ããç¶æ¿ãããå Žåãã³ã³ãã€ã©ãŒã¯msg_accessors_t
ã³ã³ã¹ãã©ã¯ã¿ãŒãšã³ããŒæŒç®åãçæã§ããªãããšã«æ³šæããããšãéèŠmsg_accessors_t
ã ãããå¿
èŠãªãã®ã§ãã
ã¡ãã»ãŒãžã®ã¿ã€ããã²ãã¿ãŒã«ãã£ãŠè¿ããããã€ã³ã¿ãŒ/ãªã³ã¯ã¯ãReturn_Typeãã©ã¡ãŒã¿ãŒãšããŠæ©èœããŸãã ç§Theã¯ãã¿ã€ãMsg
äžå€ã¡ãã»ãŒãžã®Msg
ãReturn_Typeãã©ã¡ãŒã¿ãŒãconst Msg
èšå®ãããããšã§ãã äžæ¹ãã¿ã€ãMsg
å¯å€ã¡ãã»ãŒãžã®Msg
ãã©ã¡ãŒã¿ãŒReturn_Typeã®å€ã¯Msg
ãŸãã ãããã£ãŠã get()
ã¡ãœããã¯ãäžå€ã¡ãã»ãŒãžã®å Žåã¯const Msg*
ãè¿ããå¯å€ã¡ãã»ãŒãžã®å Žåã¯Msg*
ã®ã¿ãè¿ããŸãã
ç¡æã®é¢æ°get_ptr()
ã䜿çšãããšã message_t
ããç¶æ¿ãããŠããªãã¡ãã»ãŒãžãåŠçget_ptr()
åé¡message_t
解決ãããŸãã
template< typename M > M * get_ptr( const intrusive_ptr_t<M> & msg ) noexcept { return msg.get(); } template< typename M > M * get_ptr( const intrusive_ptr_t< user_type_message_t<M> > & msg ) noexcept { return std::addressof(msg->m_payload); }
ã€ãŸã ã¡ãã»ãŒãžãmessage_t
ããç¶æ¿ããuser_type_message_t<Msg>
ã user_type_message_t<Msg>
ãšããŠä¿åãããŠããå Žåã2çªç®ã®ãªãŒããŒããŒããåŒã³åºãããŸãã ãããŠããããç¶æ¿ãããå Žåãæåã®ãªãŒããŒããŒãã
ã²ãã¿ãŒã®ç¹å®ã®ããŒã¹ãéžæãã
ãã®ããã msg_accessors_t
ãã³ãã¬ãŒãã«ã¯2ã€ã®ãã©ã¡ãŒã¿ãŒãå¿
èŠã§ãã æåã¯impl_selector
ã¡ã¿é¢æ°ã«ãã£ãŠèšç®ãããŸãã ãã ãã msg_accessors_t
ããç¹å®ã®åºæ¬åãmsg_accessors_t
ããã«ã¯ã2çªç®ã®ãã©ã¡ãŒã¿ãŒã®å€ã決å®ããå¿
èŠããããŸãã ãã1ã€ã®ã¡ã¿æ©èœããããç®çãšããŠããŸãã
template< message_mutability_t Mutability, typename Base > struct accessor_selector { using type = std::conditional_t< message_mutability_t::immutable_message == Mutability, msg_accessors_t<Base, typename Base::payload_type const>, msg_accessors_t<Base, typename Base::payload_type> >; };
Return_Typeãã©ã¡ãŒã¿ãŒã®èšç®ã«ã®ã¿æ³šæãæãããšãã§ããŸãã east constãæçšãªæ°å°ãªãã±ãŒã¹ã®1ã€ã§ã;ïŒ
ããŠãåŸç¶ã®ã³ãŒãã®å¯èªæ§ãé«ããããã«ããããæ±ãããã®ããã³ã³ãã¯ããªãªãã·ã§ã³ïŒ
template< message_mutability_t Mutability, typename Base > using accessor_selector_t = typename accessor_selector<Mutability, Base>::type;
æçµæ¿ç¶è
message_holder_t
ããã§ããããã®ãã¹ãŠã®åºæ¬ã¯ã©ã¹ãšã¡ã¿é¢æ°ãå¿
èŠãªå®è£
ã®ããã«ã message_holder_t
äœã§ããããèŠãããšãã§ããŸãïŒmessage_holderã«ä¿åãããã¡ãã»ãŒãžã®ã€ã³ã¹ã¿ã³ã¹ãæ§ç¯ããããã®å®è£
ããããã€ãã®ã¡ãœãããåé€ãããŸããïŒïŒ
template< typename Msg, message_ownership_t Ownership = message_ownership_t::autodetected > class message_holder_t : public details::message_holder_details::accessor_selector_t< details::message_mutability_traits<Msg>::mutability, details::message_holder_details::impl_selector_t<Msg, Ownership> > { using base_type = details::message_holder_details::accessor_selector_t< details::message_mutability_traits<Msg>::mutability, details::message_holder_details::impl_selector_t<Msg, Ownership> >; public : using payload_type = typename base_type::payload_type; using envelope_type = typename base_type::envelope_type; using base_type::base_type; friend void swap( message_holder_t & a, message_holder_t & b ) noexcept { using std::swap; swap( a.message_reference(), b.message_reference() ); } };
å®éãäžèšã®2ã€ã®ã¡ã¿é¢æ°ã®ãåŒã³åºãããèšé²ããã«ã¯ãäžèšã§åæãããã¹ãŠãå¿
èŠã§ããã
details::message_holder_details::accessor_selector_t< details::message_mutability_traits<Msg>::mutability, details::message_holder_details::impl_selector_t<Msg, Ownership> >
ãªããªã ããã¯æåã®ãªãã·ã§ã³ã§ã¯ãããŸããããã³ãŒãã®ç°¡çŽ åãšåæžã®çµæãã¡ã¿é¢æ°ã®ã³ã³ãã¯ããªãã©ãŒã ã¯ã³ãŒãã®éã倧å¹
ã«åæžãããã®ç解床ãé«ããŠãããšèšããŸãïŒããã§äžè¬çã«ç解床ã«ã€ããŠè©±ãã®ãé©åãªå ŽåïŒã
ãããŠãã©ããªãã§ããã...
ããããC ++ã§if constexpr
ãDã§static if
ããã匷åã§static if
ã次ã®ããã«æžãããšãã§ããŸãã
constexprã®ããé«åºŠãªä»®æ³ãªãã·ã§ã³ template< typename Msg, message_ownership_t Ownership = message_ownership_t::autodetected > class message_holder_t { static constexpr const message_mutability_t Mutability = details::message_mutability_traits<Msg>::mutability; static constexpr const message_ownership_t Actual_Ownership = (message_ownership_t::unique == Ownership || (message_mutability_t::mutable_msg == Mutability && message_ownership_t::autodetected == Ownership)) ? message_ownership_t::unique : message_ownership_t::shared; public : using payload_type = typename message_payload_type< Msg >::payload_type; using envelope_type = typename message_payload_type< Msg >::envelope_type; private : using getter_return_type = std::conditional_t< message_mutability_t::immutable_msg == Mutability, payload_type const, payload_type >; public : message_holder_t() noexcept = default; message_holder_t( intrusive_ptr_t< envelope_type > mf ) noexcept : m_msg{ std::move(mf) } {} if constexpr(message_ownership_t::unique == Actual_Ownership ) { message_holder_t( const message_holder_t & ) = delete; message_holder_t( message_holder_t && ) noexcept = default; message_holder_t & operator=( const message_holder_t & ) = delete; message_holder_t & operator=( message_holder_t && ) noexcept = default; } friend void swap( message_holder_t & a, message_holder_t & b ) noexcept { using std::swap; swap( a.m_msg, b.m_msg ); } [[nodiscard]] getter_return_type * get() const noexcept { return get_const_ptr( m_msg ); } [[nodiscard]] getter_return_type & operator * () const noexcept { return *get(); } [[nodiscard]] getter_return_type * operator->() const noexcept { return get(); } if constexpr(message_ownership_t::shared == Actual_Ownership) { [[nodiscard]] intrusive_ptr_t< envelope_type > make_reference() const noexcept { return m_msg; } } else { [[nodiscard]] intrusive_ptr_t< envelope_type > make_reference() noexcept { return { std::move(m_msg) }; } } private : intrusive_ptr_t< envelope_type > m_msg; };
ç§ã«ãšã£ãŠããã®éãã¯ããŸãã«ãé¡èã§ãã ãããŠã圌ãã¯çŸåšã®C ++ãæ¯æããŠããŸãã:(
( C++ "" ).
, , ++. , , , . , message_holder_t
. , , if constexpr
.
ãããã«
ç§ã®å Žåããã®äŸã¯C ++ã®ãã¹ãŠã®çŽ æŽããããšè²§å°ã瀺ããŠããŸããã¯ãã奜ããªãã®ãäœæã§ããŸããããæå³ã§ã¯ããã³ãã¬ãŒãã¯ã©ã¹ãäœæã§ããŸãããã³ãã¬ãŒãã¯ã©ã¹ã®å
容ã¯ããã³ãã¬ãŒããã©ã¡ãŒã¿ã«å¿ããŠæ ¹æ¬çã«å€åããŸãã
ãã ãããããè¡ãã«ã¯ãé ãããå£ãããã³ãã¬ãŒãã«éåžžã«å€ãã®è£å©ã³ãŒããèšè¿°ããå¿
èŠããããããäœæè
ã§ããããã®ãã¹ãŠã詳ãã調ã¹ãããªãã§ãããã
ããã«ãããããããC ++ã§ãããè¡ãããšãã§ãããšããäºå®ã¯ãç§ãå人çã«å¹žãã«ããŸããããã¯ãå¿
èŠãªäœæ¥éãšã³ãŒãéãæ··ä¹±ãããŸããããããæéã®çµéãšãšãã«ããã®ã³ãŒãã®éãšãã®è€éããæžå°ããããšãé¡ã£ãŠããŸããååãšããŠãããã¯ãã§ã«èŠããŠããŸããC ++ 98/03ã®å Žåãç§ã¯ãã®ãããªããªãã¯ãåŒãåããããšããããŸããããC ++ 11ããå§ãããšããããããç°¡åã«ãªããŸãã