ã²ãŒã ã®ããã°ããã±ããã®èªã¿åããšæžã蟌ã¿ãã®Gafferã®çŽ æŽããã
èšäºãšããã¹ãŠïŒãã¹ãŠC ++ã§ã³ãŒããæžãïŒïŒ
åé¡ã®ã¹ããŒãã¡ã³ãããå§ããŸãããã ãããã¯ãŒã¯ã²ãŒã ãäœæããŠããŸãïŒãã¡ãããããã«MMORPGãïŒïŒããŸããã¢ãŒããã¯ãã£ã«é¢ä¿ãªãããããã¯ãŒã¯ãä»ããŠããŒã¿ãåžžã«éåä¿¡ããå¿
èŠããããŸãã ã»ãšãã©ã®å Žåãããã€ãã®ç°ãªãçš®é¡ã®ããã±ãŒãžïŒãã¬ãŒã€ãŒã®ã¢ã¯ã·ã§ã³ãã²ãŒã ã¯ãŒã«ãã®æŽæ°ãåçŽã«èªèšŒãªã©ïŒãéä¿¡ããå¿
èŠããããŸãããããŠãããããã«èªã¿åãé¢æ°ãšæžã蟌ã¿é¢æ°ãå¿
èŠã§ãã èœã¡çããŠãããã®2ã€ã®é¢æ°ãèœã¡çããŠèšè¿°ããç·åŒµããªãããšã¯åé¡ã§ã¯ãªãããã«æããŸãããããã«å€ãã®åé¡ãçºçããŸãã
- ãã©ãŒãããã®éžæã JavaScriptã§ç°¡åãªã²ãŒã ãäœæããå ŽåãJSONãŸãã¯ãã®èª¬æçãªèŠªwithã«æºè¶³ããŸãã ããããç§ãã¡ã¯ãã©ãã£ãã¯ãèŠæ±ããæ·±å»ãªãã«ããã¬ã€ã€ãŒã²ãŒã ãæžããŠããŸãã 4ãã€ãã§ã¯ãªãã16ãã€ãããããŒãã«éä¿¡ããäœè£ã¯ãããŸããã ãããã£ãŠãçã®ãã€ããªåœ¢åŒãå¿
èŠã§ãã ãã ãããã€ããªããŒã¿ã¯ãããã°ãè€éã«ããŸãã ãã¹ãŠã®èªã¿åã/æžã蟌ã¿æ©èœãå®å
šã«æžãæããããšãªãããã€ã§ããã©ãŒããããå€æŽã§ãããšäŸ¿å©ã§ãã
- ã»ãã¥ãªãã£ã®æžå¿µã ãããã¯ãŒã¯ã²ãŒã ã®æåã®ã«ãŒã«ïŒ ã¯ã©ã€ã¢ã³ãããéä¿¡ãããããŒã¿ãä¿¡é Œããªãã§ãã ãã ïŒ èªã¿åãæ©èœã¯ãã€ã§ãäžæã§ããäœãåé¡ãçºçããå Žåã¯
false
ãè¿ãããšãã§ããŸãã ãã ããäŸå€ã䜿çšããã®ã¯é
ããããããéèŠã§ã¯ãªããšèããããŸãã Momkinã®ããã«ãŒã¯ãããšãããªãã®ãµãŒããŒãç Žå£ããªããŠããç¶ç¶çã«å®è¡ããããšã§ãµãŒããŒã®é床ãäœäžãããããšãã§ããŸãã ããããifãšreturnã§æ§æãããã³ãŒããæåã§èšè¿°ããããšã¯ãäžå¿«ã§èŠãç®ãæªãã§ãã - ã³ãŒããéè€ããŠããŸãã èªã¿åãæ©èœãšæžã蟌ã¿æ©èœã¯äŒŒãŠããŸãããå®å
šã§ã¯ãããŸããã ããã±ãŒãžã®æ§é ãå€æŽããå¿
èŠããããšã 2ã€ã®æ©èœãå€æŽããå¿
èŠãçããé
ããæ©ããããããã1ã€ãå€æŽããã®ãå¿ããããç°ãªãæ¹æ³ã§å€æŽãããããããšã«ãªãããã£ãããã«ãããã°ã«ã€ãªãããŸãã Gaffer on Gamesãæ£ãã芳å¯ããŠããããã«ã èªã¿åãæ©èœãšæžã蟌ã¿æ©èœãå¥ã
ã«ç¶æããã®ã¯æ¬åœã«é¢åã§ãã
ãã³ããŒãã©ã®ããã«çŽæãæãããåæã«ç¹å®ãããåé¡ã解決ãããã«èå³ããã人ã¯ãç«ã®äžã§ãé¡ãããŸãã
ã¹ããªãŒã ã®èªã¿åããšæžã蟌ã¿
æåã®ä»®å®ããå§ããŸãããã ããã¹ããšãã€ããªåœ¢åŒãèªã¿æžãã§ããããã«ãããã ããã¹ã圢åŒãæšæºã®STLã¹ããªãŒã ããèªã¿åã/
std::basic_istream
ãŸãïŒãããã
std::basic_istream
ããã³
std::basic_ostream
ïŒã ãã€ããªåœ¢åŒã®å Žåãã¹ããªãŒã ãšåæ§ã®STLã€ã³ã¿ãŒãã§ã€ã¹ããµããŒãããç¬èªã®
BitStream
ã¯ã©ã¹ããããŸãïŒå°ãªããšã
<<
ããã³
>>
æŒç®åãèªã¿åã/æžã蟌ã¿ãšã©ãŒããªãå Žåã¯0ãè¿ãããã®ä»ã®å Žåã¯0ãè¿ããªã
rdstate()
ã¡ãœãããããã³
ãããã¥ã¬ãŒã¿ãŒãé£ã¹ãæ©èœïŒ ; ãŸãã8ãããã®åæ°ã§ã¯ãªãé·ãã®ããŒã¿ãèªã¿æžãã§ãããšãã°ãããã§ãããã
å¯èœãªBitStreamã¯ã©ã¹ã€ã³ã¿ãŒãã§ã€ã¹ using byte = uint8_t; class BitStream { byte* bdata; uint64_t position; uint64_t length, allocated; int mode;
enable_ifãããã«ããã®ã¯ãªãã§ããïŒstd::enable_if<condition, T>
ã¯ãæ¡ä»¶
condition
ããã§ãã¯ããæ¡ä»¶ãæºããããå ŽåïŒã€ãŸãããŒãã«çãããªãå ŽåïŒãã¿ã€ã
std::enable_if<...>::type
決å®ãããŠãŒã¶ãŒãæå®ããã¿ã€ã
T
ãŸãã¯ããã©ã«ãïŒ
void
æ¡ä»¶ãæºããããªãå Žåã
std::enable_if<...>::type
ãžã®åŒã³åºãã¯æªå®çŸ©ãè¿ããŸãã ãã®ãããªãšã©ãŒã¯ãã³ãã¬ãŒãã®ã³ã³ãã€ã«ã劚ããŸããã
眮æã®å€±æã¯ãšã©ãŒã§ã¯ãªãããïŒSFINAEïŒ ããã³ãã¬ãŒãã«åŒæ°ã代å
¥ãããšãã®ãšã©ãŒã¯ã³ã³ãã€ã«ãšã©ãŒã§ã¯ãªããããããã°ã©ã ã®ã³ã³ãã€ã«ã¯åŠšããããŸããã
operator<<
å¥ã®å®è£
ãé©åãªã·ã°ããã£ã§ã©ããã§å®çŸ©ãããŠããå ŽåããŸãã¯åŒã³åºãé©åãªé¢æ°ãåã«ãªããšããå Žåãããã°ã©ã ã¯æ£åžžã«ã³ã³ãã€ã«ãããŸãïŒã¹ããŒãã³ã³ãã€ã©ã¯ãè©Šè¡ããããšãSFINAEã§æå®ã§ããŸãïŒã
ã·ãªã¢ã©ã€ã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹
ã·ãªã¢ã©ã€ã¶ãŒã®åºæ¬çãªãããªãã¯ããå¿
èŠã§ããããšã¯æããã§ããæŽæ°ãŸãã¯æµ®åå°æ°ç¹æ°ãã·ãªã¢ã«åããã³è§£æã§ããé¢æ°ãŸãã¯ãªããžã§ã¯ãã§ãã ãã ããæã
ã¯ïŒãã¡ããïŒïŒæ¡åŒµæ§ãã€ãŸã ããã°ã©ããŒãèªåã®ããŒã¿åãã·ãªã¢ã«åããããã®ãããªãã¯ããäœæãããããã·ãªã¢ã©ã€ã¶ãŒã§äœ¿çšã§ããããã«ããŸãã ãã®ãããªã¬ã³ã¬ã¯ã©ã®ããã«èŠããã¹ãã§ããïŒ æãç°¡åãªåœ¢åŒããå§ãããŸãã
struct IntegerField { template<class OutputStream> static void serialize(OutputStream& out, int t) { out << t;
2ã€ã®éçã¡ãœãããšããããç¡å¶éã®ãªãŒããŒããŒããæã€ã¯ã©ã¹ã ïŒãããã£ãŠã1ã€ã®ãã³ãã¬ãŒãã¡ãœããã®ä»£ããã«ã
std::basic_ostream
ã«1ã€ã
BitStream
ã«1ã€ãããã°ã©ããŒã®å¥œã¿ã«åãããŠä»ã®ã¹ããªãŒã ã«ç¡å¶éã®æ°ãæžã蟌ãããšãã§ããŸããïŒ
ããšãã°ãèŠçŽ ã®åçé
åãã·ãªã¢ã«åããã³è§£æããå Žåãã€ã³ã¿ãŒãã§ã€ã¹ã¯æ¬¡ã®ããã«ãªããŸãã
template<typename T> struct ArrayField { template<class OutputStream> static void serialize(OutputStream& out, size_t n, const T* data); template<class OutputStream> static void serialize(OutputStream& out, const std::vector<T>& data); template<class InputStream> static bool deserialize(InputStream& in, size_t& n, T*& data); template<class InputStream> static bool deserialize(InputStream& in, std::vector<T>& data); };
ãã«ããŒãã¿ãŒã³can_serialize
ããã³can_deserialize
次ã«ããã®ãããªãã£ãŒã«ãããã®ãããªåŒæ°ããã³ãã®ãããªåŒæ°ã䜿çšããŠã·ãªã¢ã«å/解æãããªã¬ãŒã§ãããã©ããã確èªããæ©èœãå¿
èŠã§ãã ããã§ãå¯å€é·ãã³ãã¬ãŒããšSFINAEã®ãã詳现ãªèª¬æã«é²ã¿ãŸãã
ã³ãŒãããå§ããŸãããïŒ
template<typename... Types> struct TypeList {
ããã¯äœã§ãã ããã¯ãã³ã³ãã€ã«æ®µéã§ãæå®ãããã¯ã©ã¹
F
ãšåã®ãªã¹ã
L = TypeList<Types...>
ã«ãã£ãŠããããã®åã®åŒæ°ã§é¢æ°
F::serialize
ãåŒã³åºãããšãã§ãããã©ããã決å®ããæ§é ã§ãã äŸãã°
can_serialize<IntegerField, TypeList<BitStream&, int> >::value
1ã«çãã
can_serialize<IntegerField, TypeList<BitStream&, char&> >::value
ïŒ
char&
å®å
šã«
int
å€æãããããïŒããããã
can_serialize<IntegerField, TypeList<BitStream&> >::value
IntegerField
ã¯ãåºåã¹ããªãŒã ã®ã¿ãåãå
¥ãã
serialize
ã¡ãœãããæäŸããªãããã0ã§ãã
ã©ã®ããã«æ©èœããŸããïŒ ãã埮åŠãªè³ªåããããç解ããŸãããã
TypeList
ã¯ã©ã¹ããå§ããŸãããã ããã§ã¯ãBenderãçŽæãã
å¯å€ååŒæ°ãã³ãã¬ãŒã ãã€ãŸã
ãå¯å€åã®åŒæ°ãæ〠ãã³ãã¬ãŒãã䜿çšã
ãŸã ã
TypeList
ã¯ã©ã¹ã®ãã³ãã¬ãŒãã¯ãä»»æã®æ°ã®ååŒæ°ãåãå
¥ããŸãããããã®åŒæ°ã¯ã
Types
ãšããååã§
ãã©ã¡ãŒã¿ãŒããã¯ã«é
眮ãã
ãŸã ã ïŒ
以åã®èšäºã§ãã©ã¡ãŒã¿ãŒããã¯ã®äœ¿çšæ¹æ³ã«ã€ããŠè©³ãã説æããŸãããïŒ
TypeList
ã¯ã©ã¹ã¯äœã®åœ¹ã«ã
TypeList
ãŸããããææã¡ã®ãã©ã¡ãŒã¿ãŒããã¯ã䜿ã£ãŠå€ãã®ããšãã§ããŸãã ããšãã°ã建èš
std::declval<Ts>()...
ã¿ã€ã
T1, T2, T3, T4
ãå«ãé·ã4ã®ãã©ã¡ãŒã¿ãŒããã¯ã®å Žåã
std::declval<T1>(), std::declval<T2>(), std::declval<T3>(), std::declval<T4>()
次ã ã¯ã©ã¹
F
ãšã¿ã€ã
L
ãªã¹ãã
can_serialize
ãã³ãã¬ãŒããšããªã¹ãå
ã®ã¿ã€ãèªäœãžã®ã¢ã¯ã»ã¹ãå¯èœã«ããéšåçãªç¹æ®åããããŸãã ïŒ
can_serialize<F, L>
ãèŠæ±ãããšã
L
åã®ãªã¹ãã§
L
ãŸããããã³ã³ãã€ã©ãŒã¯æªå®çŸ©ã®ãã³ãã¬ãŒãã«ã€ããŠæå¥ãèšãã§ããããåœç¶ã®ããšã§ããïŒãã®éšåçãªç¹æ®åã§ã¯ããã¹ãŠã®éæ³ãéããŸãã
圌女ã®ã³ãŒãã«ã¯ã
sizeof
å
ã®
func<F>(0)
åŒã³åºãããããŸãã ã³ã³ãã€ã©ãŒã¯ãæ»ãå€ã®ãµã€ãºããã€ãåäœã§èšç®ããããã«ãã©ã®
func
é¢æ°ã®ãªãŒããŒããŒããåŒã³åºããããã決å®ããããã«åŒ·å¶ãããŸãããã³ã³ãã€ã«ã¯è©Šè¡ãããªãããããé¢æ°ã®å®è£
ãèŠã€ãããŸããããªã©ã®ãšã©ãŒïŒããã³ãšã©ãŒãé¢æ°ã®æ¬äœã«ããçš®ã®ããããã®çš®é¡ãïŒãã®æ¬äœããã£ãå ŽåïŒã æåã«ã圌ã¯
func
ã®æåã®å®çŸ©ãéåžžã«è€éãªå€èŠ³ã䜿çšããããšããŸãã
template <typename U> static char func( decltype( U::serialize( std::declval<Ts>()... ) )* );
decltype
ã³ã³ã¹ãã©ã¯ã
decltype
æ¬åŒ§ã§å²ãŸããåŒ
decltype
ã¿ã€ãã
decltype
ã ããšãã°ã
decltype(10)
ã¯
int
ãšåãã§ãã ãã ãã
sizeof
ãšåæ§ã«ãã³ã³ãã€ã«ããŸããã ããã«ããããã©ãŒã«ã¹ã
std::declval
ã§äœ¿çšã§ããŸãã
std::declval
ã¯ãå¿
èŠãªåã®å³èŸºå€åç
§ãè¿ã
ãµããããé¢æ°ã§ãã ããã¯åŒ
U::serialize( std::declval<Ts>()... )
æå³ã®ãããã®ã«ããåŒæ°ã®ååã«ããã©ã«ãã®ã³ã³ã¹ãã©ã¯ã¿ããªããåã«
U::serialize( Ts()... )
æžãããšãã§ããªãå Žåã§ããå®éã®
U::serialize
åŒã³åºããæš¡å£ããŸã
U::serialize( Ts()... )
ïŒãã®é¢æ°ã¯å·ŠèŸºå€åç
§ãå¿
èŠãšããããšã¯èšããŸã§ããããŸããïŒã¡ãªã¿ã«ããã®å Žåã
declval
ã¯å·ŠèŸºå€åç
§ãäžããŸããããã¯ãC ++
T& &&
declval
ã
T& &&
çããããã§ãïŒã ãã¡ãããå®è£
ã¯ãããŸããã ãã¬ãŒã³ã³ãŒãã§æžã
int a = std::declval<int>();
æªãèãã§ãã
ã ããããã«ã
decltype
å
ã§ã®
decltype
äžå¯èœãªå ŽåïŒãã®ãããªã·ã°ããã£ãæã€é¢æ°ããªããããã®çœ®æãäœããã®çç±ã§ãšã©ãŒãåŒãèµ·ããïŒ-ã³ã³ãã€ã©ãŒã¯ã眮æãšã©ãŒãçºçãããšèŠãªããŸããããã¯ãåãã®ãšããããšã©ãŒã§ã¯ãããŸããïŒSFINAEïŒã ãããŠã圌ã¯å·éã«ããã«é²ãã§ã次ã®
func
å®çŸ©ã䜿çšããããšããŸãã ãã ããå¥ã®é¢æ°ã¯ç°ãªããµã€ãºã®çµæãè¿ããŸããããã¯ã
sizeof
ã䜿çšããŠç°¡åã«ãã£ããã£ã§ããŸãã ïŒå®éãããã»ã©ç°¡åã§ã¯ãªãã
sizeof(long)
ã¯ããšããŸããã¯ãªãã©ãããã©ãŒã ã§ã¯
sizeof(char)
ã«çãããªãå¯èœæ§ããããŸããããããã®è©³çŽ°ãçç¥ããŸã-ããã¯ãã¹ãŠä¿®æ£å¯èœã§ããïŒ
èªå·±åæ ã®ç³§ãšããŠã
can_deserialize
ãã³ãã¬ãŒãã®ã³ãŒããæäŸããŸããããã¯ãããå°ãè€éã§ã
F::deserialize
ãæå®ãããã¿ã€ãã®åŒæ°ã§
can_deserialize
ãã©ããããã§ãã¯ããã ãã§ãªããçµæã¿ã€ãã
bool
ã§ããããšã確èªããŸãã
template<typename F, typename L> class can_deserialize; template<typename F, typename... Ts> class can_deserialize<F, TypeList<Ts...>> { template <typename U> static char func( typename std::enable_if< std::is_same<decltype(U::deserialize(std::declval<Ts>()...)), bool>::value >::type* ); template <typename U> static long func(...); public: using type = can_deserialize; static const bool value = ( sizeof(func<F>(0)) == sizeof(char) ); };
ã¬ã³ã¬ã®ããã±ãŒãžãåéããŸã
æåŸã«ãã·ãªã¢ã©ã€ã¶ã®ã³ã³ãã³ãã«åãçµãæãæ¥ãŸããã ã€ãŸããããªãã¯ããã¢ã»ã³ãã«ãããé¢æ°ã
deserialize
serialize
ããã³
deserialize
serialize
ãã
Schema
ãã³ãã¬ãŒãã¯ã©ã¹ãååŸããå¿
èŠããããŸãã
using MyPacket = Schema<IntegerField, IntegerField, FloatField, ArrayField<float>>; MyPacket::serialize(std::cout, 10, 15, 0.3, 0, nullptr); int da, db; float fc; std::vector<float> my_vector; bool success = MyPacket::deserialize(std::cin, da, db, fc, my_vector);
åçŽãªãã®ããå§ããŸããã-ãã³ãã¬ãŒãã¯ã©ã¹ã宣èšããŸãïŒåŒæ°ã®æ°ãå¯å€ãnyïŒïŒãããŠååž°ã®çµããã§ãã
template<typename... Fields> struct Schema; template<> struct Schema<> { template<typename OutputStream> static void serialize(OutputStream&) {
ãããããã£ãŒã«ãã®æ°ããŒãã§ãªãåè·¯ã§ã¯ã
serialize
é¢æ°ã³ãŒãã¯ã©ã®ããã«èŠããã¹ãã§ããããïŒ äºåã«ãããããã¹ãŠã®ãã£ãŒã«ãã®
serialize
é¢æ°ã§åãå
¥ããããåãèšç®ããããšã¯ã§ãããããããé£çµããããšãã§ããŸãããããã«ã¯ãæšæºã«ãŸã å«ãŸããŠããªã
åŒã³åºãåç¹æ§ãå¿
èŠã«ãªã
ãŸã ã æ®ã£ãŠããã®ã¯ãå¯å€æ°ã®åŒæ°ã䜿çšããŠé¢æ°ãäœæããåãã£ãŒã«ãã«é£ã¹ãããéãå€ãã®åŒæ°ãéä¿¡ããããšã§ããããã§ã¯ãèŠçã®äžã§çãŸãã
can_serialize
ã䜿çšã§ããŸãã
åŒæ°ã®æ°ã®èŠ³ç¹ãããã®ååž°ãè¡ãã«ã¯ããã«ããŒã¯ã©ã¹ãå¿
èŠã§ãïŒã¡ã€ã³ã®
Schema
ã¯ã©ã¹ã¯ããã£ãŒã«ãã®æ°ã®ååž°ãåŠçããŸãïŒã åŒæ°ãå¶éããã«å®çŸ©ããŸãïŒ
template< typename F,
次ã«ã
Schema
ã®éšåçãªç¹æ®åã¯ãæçµçã«ãã£ãŒã«ãæ°ã«ããååž°ãå®è£
ãã次ã®åœ¢åŒãåããŸã
template<typename F, typename... Fields> struct Schema<F, Fields...> { template< typename OutputStream,
次ã«ã
SchemaSerializer
ååž°ã
SchemaSerializer
ãŸãã ç°¡åãªãã®ããå§ããŸããã-æåŸããïŒ
template<typename F, typename NextSerializer, typename OS> struct SchemaSerializer<F, NextSerializer, OS, TypeList<>, false> {
ããã§ããã³ããŒãçŽæãã2çªç®ã®æŠå¿µã
ã€ãŸãå®å
šãªè»¢éã«é²ã¿ãŸãã è¿œå ã®åŒæ°ïŒåŒæ°ã¯ãªããããããŸãããããããããªãïŒãããããããã
NextSerializer::serialize
ããã«éä¿¡ãããã§ãã ãã³ãã¬ãŒãã®å Žåãããã¯å®å
šè»¢éã®åé¡ãšããŠç¥ãããåé¡ã§ãã
å®ç§ãªè»¢é
1ã€ã®åŒæ°ãåããã³ãã¬ãŒãé¢æ°
f
ã©ãããŒãäœæãããšããŸãã äŸãã°
template<typename T> void better_f(T arg) { std::cout << "I'm so much better..." << std::endl; f(arg); }
èŠãç®ã¯è¯ãããã§ããã
f
T&
ã ãã§ãªã巊蟺å€ãªã³ã¯
T&
ãå
¥åãšããŠåãå
¥ãããšãããã«å£ããŸããå
ã®é¢æ°
f
ã¯ãå
¥åãšããŠäžæãªããžã§ã¯ããžã®ãªã³ã¯ãåãåããŸããããã¯ãã¿ã€ãTã¯ãªã³ã¯ã®ãªãã¿ã€ããšããŠæšå®ãããããã§ãã 解決çã¯ç°¡åã§ãã
template<typename T> void better_f(T& arg) { std::cout << "I'm so much better..." << std::endl; f(arg); }
ãŸãã
f
ãå€ã§åŒæ°ãåãå Žåãããã«å£ããŸãããªãã©ã«ãä»ã®å³èŸºå€ãå
ã®é¢æ°ã«éä¿¡ã§ããŸããããæ°ããé¢æ°ã«ã¯éä¿¡ã§ããŸããã§ããã
ã³ã³ãã€ã©ãŒãéžæã§ããäž¡æ¹ã®å Žåã«å®å
šãªäºææ§ãååšããããã«ãäž¡æ¹ã®ãªãã·ã§ã³ãèšè¿°ããå¿
èŠããããŸãã
template<typename T> void better_f(T& arg) { std::cout << "I'm so much better..." << std::endl; f(arg); } template<typename T> void better_f(const T& arg) { std::cout << "I'm so much better..." << std::endl; f(arg); }
ãããŠã1ã€ã®åŒæ°ãæã€1ã€ã®é¢æ°ã®ãã¹ãŠã®ãµãŒã«ã¹ã åŒæ°ã®æ°ãå¢ãããšãæ¬æ Œçãªã©ãããŒã«å¿
èŠãªãªãŒããŒããŒãã®æ°ãææ°é¢æ°çã«å¢ããŸãã
ããã«å¯ŸåŠããããã«ãC ++ 11ã§ã¯å³èŸºå€åç
§ãšæ°ããåèšç®èŠåãå°å
¥ãããŠããŸãã ä»ãããªãã¯ç°¡åã«æžãããšãã§ããŸã
template<typename T> void better_f(T&& arg) { std::cout << "I'm so much better..." << std::endl;
åèšç®ã®ã³ã³ããã¹ãã§ã®&&修食åã«ã¯ç¹å¥ãªæå³ããããŸãïŒãã ããéåžžã®å³èŸºå€åç
§ãšæ··åããã®ã¯ç°¡åã§ãïŒã ã¿ã€ã
type
ãªããžã§ã¯ããžã®å·ŠèŸºå€åç
§ãé¢æ°ã«æž¡ãããå Žåãã¿ã€ãTã¯
type&
ãšããŠæšæž¬ãããŸãã ã¿ã€ã
type
å³èŸºå€ãæž¡ãããå Žåãã¿ã€ãTã¯
type&&
ãšããŠæšæž¬ãããŸãã æ¢å®ã®åŒæ°ãäžå¿
èŠã«ã³ããŒããããšãªããå®å
šã«å®å
šã«è»¢éããããã«æåŸã«è¡ãããšã¯ã
std::forward
ã䜿çšããããš
std::forward
ã
template<typename T> void better_f(T&& arg) { std::cout << "I'm so much better..." << std::endl; f(std::forward<T>(arg)); }
std::forward
ã¯éåžžã®ãªã³ã¯ã«è§Šãããå€ã«ãã£ãŠæž¡ããããªããžã§ã¯ããå³èŸºå€ãªã³ã¯ã«å€æããŸãã ãããã£ãŠãæåã®ã©ãããŒã®åŸãå³èŸºå€ãªã³ã¯ã¯ãªããžã§ã¯ãèªäœã®ä»£ããã«ã©ãããŒã®ãã§ãŒã³ïŒååšããå ŽåïŒãããã«äžã£ãŠãäžèŠãªã³ããŒãæé€ããŸãã
ã·ãªã¢ã©ã€ã¶ãŒã®ç¶ç¶
ã ãã建èš
NextSerializer::serialize(out, std::forward<TailArgs>(targs)...);
å®å
šãªè»¢éãå®è£
ãããã¹ãŠã®ãäœåãªãåŒæ°ãå€æŽããã«ã·ãªã¢ã©ã€ã¶ãŒã®ãã§ãŒã³ã®äžæµã«éä¿¡ããŸãã
SchemaSerializer
ååž°ãæžãç¶ã
SchemaSerializer
ã
can_serialize = false
ååž°ã¹ãããïŒ
template<typename F, typename NextSerializer, typename OS, typename... Types> struct SchemaSerializer<F, NextSerializer, OS, TypeList<Types...>, false>:
åãªã¹ãããæåŸã®èŠçŽ ãåãé¢ããã«ããŒã¯ã©ã¹Headã®å®è£
template<typename T> struct Head;
can_serialize = true
ååž°ã¹ãããïŒ
template<typename F, typename NextSerializer, typename OS, typename... Types> struct SchemaSerializer<F, NextSerializer, OS, TypeList<Types...>, true> { template<typename... TailTypes>
III ...以äžã§ãïŒ ããã§ãã·ãªã¢ã©ã€ã¶ãŒïŒæãäžè¬çãªçšèªã§ïŒã®æºåãæŽããæãç°¡åãªã³ãŒã
using MyPacket = Schema< IntegerField, IntegerField, CharField >; MyPacket::serialize(std::cout, 777, 6666, 'a');
æ£åžžã«è¡šç€ºãããŸã
7776666a
ããããããããã·ãªã¢ã©ã€ãºããæ¹æ³ã¯ïŒ ããã§ãã¹ããŒã¹ãè¿œå ããå¿
èŠããããŸãã ãããè¡ãããã®é©åãªïŒã€ãŸããTru-C ++ã«ååãªæœè±¡ïŒæ¹æ³ã¯ããã£ãŒã«ãã»ãã¬ãŒã¿ãããã¥ã¬ãŒã¿ããã¡ã€ã«ããããšã§ãã
template< class CharT, class Traits > std::basic_ostream<CharT, Traits>& delimiter( std::basic_ostream<CharT, Traits>& os ) { return os << CharT(' ');
std::basic_ostream
ã¯ããããžã®ãªã³ã¯ãåãå
¥ããŠè¿ãé¢æ°ãé£ã¹ãããšãã§ããããïŒ
std::endl
ã
std::flush
ïŒãã©ã®ããã«æ§æãããŠãããšæããŸããïŒããã¹ãŠã®ã·ãªã¢ã«åã³ãŒãã
serialize(OS& out, ...) { F::serialize(out, ...); out << delimiter;
ãã®åŸãèªç¶ã«ãªããŸãïŒãããŠãã·ãªã¢ã«å解é€ã®æºåãã§ããŸããïŒ
777 6666 a
ãããããŸã 现ããéšåãæ®ã£ãŠããŸã...
ãã¹ãã£ã³ã°
ç§ãã¡ã®åè·¯ã¯åçŽãªãã£ãŒã«ããšåãã€ã³ã¿ãŒãã§ãŒã¹ãæã£ãŠããã®ã§ããªãåè·¯ããåè·¯ãäœæããŸãããïŒ
using MyBigPacket = Schema<MyPacket, IntegerField, MyPacket>; MyBigPacket::serialize(std::cout, 11, 22, 'a', 33, 44, 55, 'b');
iiiiãã³ã³ãã€ã«ããŸã... 'serialize'ã®åŒã³åºãã«äžèŽããé¢æ°ããããŸããã åé¡ã¯äœã§ããïŒ
å®éã
Schema::serialize
ã¯äžãããããã¹ãŠã®åŒæ°ã䜿ãæãããŸãã å€éšåè·¯ã¯ã
Schema::serialize
ãã¹ããŒããããã¹ãŠã®åŒæ°ã§åŒã³åºããããšã確èªããŸãã ã³ã³ãã€ã©ãŒã¯ã³ã³ãã€ã«ããæåŸã®4ã€ã®åŒæ°ã
æ©èœããŠããªãããšã確èªã ïŒ
åè£é¢æ°ãã³ãã¬ãŒãã¯å®è¡äžå¯ïŒ1ã€ã®åŒæ°ã
å¿
èŠã§ããã5ã€ãæäŸãããŸãã ïŒããšã©ãŒãå ±åããŸãã
SFINAEã®å©ç¹ã¯ãæ¬ ç¹ãšããŠããã«asããŸããã ã³ã³ãã€ã©ã¯ãæå®ãããåŒæ°ã§åŒã³åºãããšãã§ãããã©ãããå€æããåã«ãé¢æ°ãã³ã³ãã€ã«ããŸããã 圌ã¯åœŒå¥³ã®ã¿ã€ããèŠãŠããã ãã§ãã ãã®äžèŠãªåäœãæé€
Schema::serialize
ã«ã¯ãäžé©åãªåŒæ°ãæž¡ãããå Žåã
Schema::serialize
匷å¶çã«ç¡å¹ãªåã«
Schema::serialize
å¿
èŠããããŸãã
ãããããã«çŽæ¥ãªããã£Schema
ãšSchemaSerializer
-ããã¯ç°¡åã§ããSchema
ãããæ¢ã«è¡ãããé¢æ°serialize
ã«ç¡å¹ãªåŒæ°ãæã€ç¡å¹ãªåããããšä»®å®ããŸããã¯ã©ã¹ã®ç¹æ®åãå€æŽããŸãSchemaSerializer
ïŒ template<typename F, typename NextSerializer, typename OS> struct SchemaSerializer<F, NextSerializer, OS, TypeList<>, true> { template<typename... TailArgs> static auto serialize(OS& out, TailArgs&&... targs) -> decltype(NextSerializer::serialize(out, std::forward<TailArgs>(targs)...)) { F::serialize(out); out << delimiter; NextSerializer::serialize(out, std::forward<TailArgs>(targs)...); } }; template<typename F, typename NextSerializer, typename OS, typename... Types> struct SchemaSerializer<F, NextSerializer, OS, TypeList<Types...>, true> { template<typename... TailTypes> static auto serialize(OS& out, Types... args, TailTypes&&... targs) -> decltype(NextSerializer::serialize(out, std::forward<TailTypes>(targs)...)) { F::serialize(out, std::forward<Types>(args)...); out << delimiter; NextSerializer::serialize(out, std::forward<TailTypes>(targs)...); } };
ã©ããã æåã«ãæ°ããæ§æã䜿çšããŸãããC ++ 11以éã§ã¯ãé¢æ°ã®çµæã®åãèšå®ããããã®æ¬¡ã®ã¡ãœããã¯åçã§ãã type func(...) { ... } auto func(...) -> type { .. }
ãªããããå¿
èŠãªã®ã§ããïŒ
å Žåã«ãã£ãŠã¯ããã䟿å©ã§ããããšãã°ãåŒc std::declval
ã®2çªç®ã®ããŒãžã§ã³ã®æ§æã§ã¯ãé¢æ°ã®åŒæ°ãæ¢ã«äœ¿çšå¯èœã«ãªã£type
ãŠãããæåã®-no ã§ã¯ããã©ãŒã«ã¹cãå床䜿çšããã«ç®çãéæã§ããŸãããããŠãç§ãã¡ã¯å®éã«äœãéæããŸãããïŒãããã次ã®ãšããã§ããååž°ãå£ããŠãæå®ãããåŒæ°ã§åŒã³åºãããšãã§ããªãå ŽåãåŒã³åºãã¯çœ®æãšã©ãŒãåŒãèµ·ãããŸããæ»ãå€ã®ã¿ã€ãïŒãããã£ãŠãé¢æ°å
šäœã®ã¿ã€ãïŒã¯èšç®ã§ããŸããããã®ããã«ãç§ãã¡ãåŒã³åºããšã眮æãšã©ãŒãçºçããŸãããšã©ãŒã¯æäžéšãŸã§äžæããé¢æ°ã®ã¿ã€ãã決å®ãã段éã§ããã®ãããªåŒæ°ã§åŒã³åºãããšã¯äžå¯èœã§ããããšããŠãŒã¶ãŒã«äŒããŸããNextSerialize::serialize
NextSerialize::serialize(out, std::forward<TailTypes>(targs)...)
SchemaSerializer::serialize
Schema::serialize
ãåæ§ã«ã¹ãã·ã£ã©ã€ãŒãŒã·ã§ã³ãå€æŽãSchema
ãŸãïŒ template<typename F, typename... Fields> struct Schema<F, Fields...> {
ãããïŒ
å°ãã·ã³ãã«ãªã³ãŒãã«ãªããŸãã using MyPacket = Schema< IntegerField, IntegerField, CharField >; using MyBigPacket = Schema< MyPacket, IntegerField, MyPacket >; MyBigPacket::serialize(std::cout, 11, 22, 'a', 33, 44, 55, 'b');
ã³ã³ãã€ã«ããŠæ¥œããå°å·ãã 11 22 a 33 44 55 b
ãã£ãïŒ
ãããã«
C ++ã¯å€§ããªé²æ©ãéããC ++ 11æšæºã¯ç¹ã«å€§ããªäžæ©ãèžã¿åºããŸãããã»ãŒãã¹ãŠã®ã€ãããŒã·ã§ã³ãäœç³»çã«äœ¿çšããŠãã¯ãªãŒã³ã§çŸããã·ãªã¢ã©ã€ã¶ãŒãå®è£
ããŠããŸãããããã¯ãµããŒãããŠããŸãããåãã£ãŒã«ãã®ä»»æã®æ°ã®åŒæ°ã蚱容ããåãã£ãŒã«ãã®ä»»æã®æ°ã®ãã³ãã¬ãŒããšéæšæºé¢æ°ã®ãªãŒããŒããŒãserialize
ã蚱容ããŸããä»ã®ã·ãªã¢ã©ã€ã¶ãŒããã£ãŒã«ããšããŠèš±å®¹ããŸããç§ã®æèŠã§ã¯ãäž»ãªããšã¯ããã¹ãŠã®åŒæ°ãå®å
ã«æ£ç¢ºã«æã¡èŸŒãããšã«ãããåãã£ã¹ãã殺ããªãããšã§ããSchemaDeserializer
é¢æ°ãå®è£
ãããã«ããŒã¯ã©ã¹ãèšè¿°ããæ¹æ³ãç解ããã®ã¯ç°¡åã§ãdeserialize
â . â ( , , ..), /.
Github .
() . , ! ãæž
èŽããããšãããããŸããã