ç§ã¯æè¿C ++ããããããŸãããC ++ 14ã§ã®ãªãã¬ã¯ã·ã§ã³ãå¯èœã«ããããã€ãã®æ°ããã¡ã¿ããã°ã©ãã³ã°ææ³ãå¶ç¶çºèŠããŸããã ããã€ãã®åæ©ä»ãã®äŸã ããã«ã¯ãããçš®ã®PODæ§é ãšãã®äžã®ããã€ãã®ãã£ãŒã«ãããããŸãã
struct complicated_struct { int i; short s; double d; unsigned u; };
ãã£ãŒã«ãã®æ°ãšãã®ååã¯éèŠã§ã¯ãããŸãããéèŠãªããšã¯ããã®æ§é ã䜿çšããŠæ¬¡ã®ã³ãŒããèšè¿°ã§ããããšã§ãã
#include <iostream> #include "magic_get.hpp" struct complicated_struct { /* ⊠*/ }; int main() { using namespace pod_ops; complicated_struct s {1, 2, 3.0, 4}; std::cout << "s == " << s << std::endl; // Compile time error? }
ã¡ã€ã³é¢æ°ã§ã¯ãæ§é äœã®å€æ°ãäœæããäœããã®æ¹æ³ã§éçŽã®åæåãä»ããŠåæåãããã®å€æ°ãstd :: coutã§è¡šç€ºããããšããŸãã ãããŠçŸæç¹ã§ã¯ãçè«äžãã³ã³ãã€ã«ãšã©ãŒãçºçããã¯ãã§ããæ§é ã®ã¹ããªãŒã ã«åºåæŒç®åãå®çŸ©ããªãã£ããããã³ã³ãã€ã©ã¯ããããã¹ãŠãã³ã³ãã€ã«ããŠåºåããæ¹æ³ãç¥ããŸããã ãã ããæ§é ã®å 容ãã³ã³ãã€ã«ããŠè¡šç€ºããŸãã
antoshkka@home:~$ ./test s == {1, 2, 3.0, 4}
ã³ãŒãã«æ»ãããã£ãŒã«ãã®ååãå€æŽããæ§é äœã®ååãå€æŽããå€æ°ã®ååãå€æŽãããªã©ãäœã§ãã§ããŸããã³ãŒãã¯åŒãç¶ãæ©èœããæ§é äœã®å 容ãæ£ãã衚瀺ããŸãã ä»çµã¿ãèŠãŠã¿ãŸãããã
ãã®æŒç®åã¯ãããããŒãã¡ã€ã«magicget.hppã§èª¬æãããŠãããã©ã®ããŒã¿åã§ãæ©èœããŸãã
template <class Char, class Traits, class T> std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& out, const T& value) { flat_write(out, value); return out; }
ãã®ã¹ããŒãã¡ã³ãã¯ãflat_writeã¡ãœãããåŒã³åºããŸãã flat_writeã¡ãœããã¯äžæ¬åŒ§ã衚瀺ããäžå€®ã«ããã·ã¥æååãå«ã¿ãŸãïŒ
template <class Char, class Traits, class T> void flat_write(std::basic_ostream<Char, Traits>& out, const T& val) { out << '{'; detail::flat_print_impl<0, flat_tuple_size<T>::value >::print(out, val); out << '}'; }
æååè¡ã®äžå€®ã«ã¯ãflat_tuple_size <T> ::å€ããããŸãã ããã§ãæšæºã©ã€ãã©ãªã«ã¯std :: tuple_size <std :: tuple>ããããã¿ãã«å ã®èŠçŽ æ°ãå°å ¥ãããããšã«æ³šæããå¿ èŠããããŸãã ãã ããããã§Tã¯ã¿ãã«ã§ã¯ãªããstd :: tupleã§ã¯ãªãããŠãŒã¶ãŒã¿ã€ãã§ãã ããã§ãflat_tuple_sizeã¯ãŠãŒã¶ãŒã¿ã€ãã®ãã£ãŒã«ãæ°ãåºåããŸãã
printé¢æ°ã®æ©èœãããã«èŠãŠã¿ãŸãããã
template <std::size_t FieldIndex, std::size_t FieldsCount> struct flat_print_impl { template <class Stream, class T> static void print (Stream& out, const T& value) { if (!!FieldIndex) out << ", "; out << flat_get<FieldIndex>(value); // std::get<FieldIndex>(value) flat_print_impl<FieldIndex + 1, FieldsCount>::print(out, value); } };
printé¢æ°ã¯ãäœæ¥ããŠãããã£ãŒã«ãã®ã€ã³ããã¯ã¹ã«å¿ããŠã³ã³ãã衚瀺ããã衚瀺ããŸããããã®åŸãflat_geté¢æ°ãåŒã³åºããŠãstd :: getã®ããã«æ©èœããããšãã³ã¡ã³ãããŸããã€ãŸããã€ã³ããã¯ã¹ããæ§é äœãããã£ãŒã«ããè¿ããŸãã èªç¶ãªçåãçããŸãïŒããã¯ã©ã®ããã«æ©èœããŸããïŒ
次ã®ããã«æ©èœããŸããã¹ããªãŒã å ã®åºåæŒç®åã¯ãæ§é å ã®ãã£ãŒã«ãæ°ã決å®ããã€ã³ããã¯ã¹ãä»ããŠãã£ãŒã«ããå埩åŠçããã€ã³ããã¯ã¹ããšã«åãã£ãŒã«ãã衚瀺ããŸãã ãããã£ãŠãèšäºã®åé ã§èŠãããšãããããŸãã
ã«ã¹ã¿ã æ§é ã§åäœããflat_getããã³flat_tuple_sizeã¡ãœãããäœæããæ§é å ã®ãã£ãŒã«ãæ°ã決å®ãããã®æ§é ããã£ãŒã«ãããšã«è¡šç€ºããæ¹æ³ãããã«èŠãŠã¿ãŸãããã
/// Returns const reference to a field with index `I` /// Example usage: flat_get<0>(my_structure()); template <std::size_t I, class T> decltype(auto) flat_get(const T& val) noexcept; /// `flat_tuple_size` has a member `value` that constins fields count /// Example usage: std::array<int, flat_tuple_size<my_structure>::value > a; template <class T> using flat_tuple_size;
ç°¡åãªãã®ããå§ããŸãããã æ§é å ã®ãã£ãŒã«ãã®æ°ãã«ãŠã³ãããŸãã PODæ§é TããããŸãã
static_assert(std::is_pod<T>::value, "")
ãã®æ§é ã«å¯ŸããŠãåŒãæžãããšãã§ããŸãïŒ
T { args... }
ããã¯éçŽæ§é ã®åæåã§ãã åŒæ°ã®æ°ãæ§é å ã®ãã£ãŒã«ãã®æ°ä»¥äžã§ãããåŒæ°ã®åã¿ã€ããæ§é å ã®ãã£ãŒã«ãã®ã¿ã€ãã«å¯Ÿå¿ããå Žåããã®åŒã¯æ£åžžã«ã³ã³ãã€ã«ãããŸãã
ãã®ã¢ãã©ã«ããã©ãããæ§é Tå ã®ãã£ãŒã«ãã®æ°ãååŸããããšããŸãããããã©ã®ããã«è¡ãã®ã§ããããã æ§é TãååŸããèšå€§ãªæ°ã®åŒæ°ã§åæåããããšããŸãã ããã¯ã³ã³ãã€ã«ãããŸããã åŒæ°ã®1ã€ãæåŠããŠãåè©Šè¡ããŸãã ãããã³ã³ãã€ã«ãããŸãããããã€ãã¯æ§é å ã®ãã£ãŒã«ãã®æ°ã«çããåŒæ°ã®æ°ã«å°éãããããçµã¿ç«ãŠãããŸãã ãã®æç¹ã§ãåŒæ°ã®æ°ãèŠããŠããã ãã§ãæºåã¯å®äºã§ããæ§é å ã«ãã£ãŒã«ãã®æ°ããããŸãã ããã¯åºæ¬çãªèãæ¹ã§ãã 詳现ã«è¡ããŸãããã
Tæ§é ã«charãŸãã¯unsigned charã®ã¿ãããã³ãã®ä»ã®ã¿ã€ãã®ãµã€ãº1ãã€ããå«ãŸããŠããå Žåãæåããäœåã®åŒæ°ãå¿ èŠã§ããïŒ ãã®å Žåãæ§é Tå ã®ãã£ãŒã«ãã®æ°ã¯ããã®æ§é ã®ãµã€ãºã«çãããªããŸãã ä»ã®ãã£ãŒã«ããããšãã°intããã€ã³ã¿ãŒãããå Žåããã£ãŒã«ãã®æ°ã¯æ§é äœã®ãµã€ãºãããå°ãªããªããŸãã
éèšã®åæåãéå§ãããã£ãŒã«ãã®æ°ãååŸããŸããã ã€ãŸããsizeofïŒTïŒã«çããåŒæ°ã®æ°ã§æ§é TãåæåããŸãã ã³ã³ãã€ã«ã«å€±æããå Žåã¯ãåŒæ°ã1ã€æ»ããŠã³ã³ãã€ã«ãçŽããæ§é å ã®ãã£ãŒã«ãã®æ°ãèŠã€ããŸããã 1ã€ã®åé¡ãæ®ã£ãŠããŸããæ§é å ã®åŒæ°ã®æ°ãæšæž¬ããŠããã³ãŒãã¯ã³ã³ãã€ã«ãããŸããã ãã£ãŒã«ãã®ã¿ã€ããæ£ç¢ºã«ç¥ãå¿ èŠãããããã§ãã
åé¿çãå®è¡ããŸãããã ä»»æã®åãžã®æé»çãªåå€æã®æŒç®åã䜿çšããŠæ§é äœãäœæããŸãã
struct ubiq { template <class Type> constexpr operator Type&() const; }; int i = ubiq{}; double d = ubiq{}; char c = ubiq{};
ã€ãŸãããã®æ§é äœã®å€æ°ã¯ãintãdoubleãstd :: stringãstd :: vectorãä»»æã®ã«ã¹ã¿ã åãªã©ãããããåã«ãã£ã¹ããããŸãã
å šäœã®ã¬ã·ãïŒTæ§é ãååŸããsizeofïŒTïŒã«çããåŒæ°ã®æ°ã§ãã®æ§é ã®åæåãéçŽããŸããååŒæ°ã¯ãubiqæ§é ã®ã€ã³ã¹ã¿ã³ã¹ã§ãã éçŽã®åæå段éã§ãubiqã®åã€ã³ã¹ã¿ã³ã¹ã¯Tæ§é å ã®ãã£ãŒã«ãã¿ã€ãã«å€ãããåŒæ°ã®æ°ã®ã¿ãéžæã§ããŸãã å€ãã®åŒæ°ãã³ã³ãã€ã«ãããŠããªãå Žåã1ã€ãç Žæ£ããŠåè©Šè¡ããŸãã ã³ã³ãã€ã«ãããå ŽåãåŒæ°ã®æ°ãèæ ®ããçµæãåŸãŸããã
ä»ãå°ãã³ãŒãã ubiqæ§é ãå°ãå€æŽããŸããå¯å€é·ãã³ãã¬ãŒãã§ãã®æ§é ã䜿çšããããããããã«ããã³ãã¬ãŒããã©ã¡ãŒã¿ãè¿œå ããŸãã ãŸããstd :: make_index_sequenceïŒstd :: index_sequence-æ°åã®é·ããã§ãŒã³ïŒã«å±éãããC ++ 14ã®ãšã³ãã£ãã£ãå¿ èŠã§ãã
æãã³ãŒããèŠãæºåã¯ã§ããŸãããïŒ è¡ãã
次ã®2ã€ã®æ©èœã®ã¿ïŒ
// #1 template <class T, std::size_t I0, std::size_t... I> constexpr auto detect_fields_count(std::size_t& out, std::index_sequence<I0, I...>) -> decltype( T{ ubiq_constructor<I0>{}, ubiq_constructor<I>{}... } ) { out = sizeof...(I) + 1; /*...*/ } // #2 template <class T, std::size_t... I> constexpr void detect_fields_count(std::size_t& out, std::index_sequence<I...>) { detect_fields_count<T>(out, std::make_index_sequence<sizeof...(I) - 1>{}); }
äž¡æ¹ã®é¢æ°ã¯ãdetect_fields_countãšåŒã°ããŸãã æåã®æ©èœã¯ããå°ãå°éçã§ãã ãããã£ãŠãã³ã³ãã€ã©ãdetect_fields_count <T>ãæ€åºãããšãæåã®é¢æ°ã¯ããç¹æ®åãããŠããã䜿çšãè©Šã¿ãå¿ èŠããããšèããããŸãã
ãã®é¢æ°ã«ã¯æ«å°Ÿã®æ»ãå€ã®åããããŸããã€ãŸãããã®é¢æ°ã®åã¯Tããã®decltypeã§ãã
éçŽã®åæåã åŒæ°ã®æ°ã§æšæž¬ããå Žåããã®åŒã¯ã³ã³ãã€ã«ããããã®é¢æ°ã®æ¬äœã«å ¥ããåºåå€æ°ã«ãæã£ãŠããåŒæ°ã®æ°ãæžã蟌ã¿ãŸãã ããŸããããªãå ŽåïŒåŒæ°ã®æ°ã¯æšæž¬ããŸããã§ããïŒãã³ã³ãã€ã©ãŒã¯ããããšã©ãŒã§ã¯ãªã眮æã®å€±æã§ãããšå€æããåãååã§å°éæ§ã®äœãå¥ã®é¢æ°ãèŠã€ããå¿ èŠããããŸãã 圌ã¯æ©èœïŒ2ãåããŸãã é¢æ°ïŒ2ã¯ãã€ã³ããã¯ã¹ã®1ã€ãç Žæ£ãïŒã€ãŸããåŒæ°ã®æ°ã1ã€æžãããŸãïŒãdetect_fields_countãå床åŒã³åºããŸãã ç¹°ãè¿ããŸãããæåã®é¢æ°ãŸãã¯2çªç®ã®é¢æ°ãåŒã³åºãããŸãã ãããã£ãŠãåŒæ°ã調ã¹ãŠãæ§é å ã®ãã£ãŒã«ãã®æ°ãèŠã€ããŸãã ããã¯ç°¡åãªéšåã§ããã
è€éãªå ïŒæ§é Tå ã®ãã£ãŒã«ãã®åãååŸããæ¹æ³ïŒ
éèšã®åæåãå«ãTåŒãæ¢ã«ãããubiqã€ã³ã¹ã¿ã³ã¹ãå éšã«æž¡ããŸãã åubiqã€ã³ã¹ã¿ã³ã¹ã«å¯ŸããŠãæé»ã®åå€ææŒç®åãåŒã³åºããããã®æŒç®åå ã®ãã£ãŒã«ãã®åãããããŸãã ä»å¿ èŠãªã®ã¯ãäœããã®æ¹æ³ã§ãã®æ å ±ãååŸããå€éšæ§é ã«åŒã蟌ã¿ãTæ§é äœã®éçŽåæåãè¶ ããŠäœæ¥ã§ããããã«ããããšã§ããæ®å¿µãªãããC ++ã«ã¯ãããŒã¿åãå€æ°ã«æžã蟌ãã¡ã«ããºã ããããŸããã ããæ£ç¢ºã«ã¯ãstd :: type_indexããã³std :: type_infoããããŸãããã³ã³ãã€ã«æ®µéã§ã¯åœ¹ã«ç«ã¡ãŸããã åŸã§ã¿ã€ããå ã«æ»ããŸããã
ã©ããããããããã®å¶éãåé¿ããŠã¿ãŸãããã ãããè¡ãã«ã¯ãPODãäœã§ããããæãåºããŠãã ããïŒéåžžã«å€§éæã«èšããšãæšæºåå§å¡äŒã¯3幎ããšã«å®çŸ©ãå€æŽããããšã奜ã¿ãŸãïŒã
PODæ§é ã¯ããã£ãŒã«ããpublicãprivateããŸãã¯protectedã®ããããã§ããŒã¯ãããŠããæ§é ã§ãïŒãããªãã¯ãã£ãŒã«ãã«ã®ã¿é¢å¿ããããŸãïŒã ãããŠããã®æ§é å ã®ãã¹ãŠã®ãã£ãŒã«ãã¯ãä»ã®PODæ§é ãŸãã¯åºæ¬ã¿ã€ãïŒãã€ã³ã¿ãŒãintãstd :: nullptr_tïŒã®ããããã§ãã æ°åéããã€ã³ã¿ãŒãå¿ããŠããŸãã32-xæªæºã®åºæ¬åã¯ã»ãšãã©ãªãããšãããããŸãããããã¯ãååºæ¬åã«ç¹å®ã®èå¥åïŒæŽæ°ïŒãå²ãåœãŠãããšãã§ããããšãæå³ããŸãã ãã®æ°åãåºåé åã«èšè¿°ãããã®åºåé åãæŒç®åã®æé»çãªå€æãè¶ ããŠåŒãåºããšãæ°åãåã³åã«å€æãããŸãã ããã¯ãšãŠãç°¡åãªã¢ã€ãã¢ã§ãã
å®è£ ãå®äºããŸããã ãããè¡ãã«ã¯ãubiqæ§é ãå€æŽããŸãã
template <std::size_t I> struct ubiq_val { std::size_t* ref_; template <class Type> constexpr operator Type() const noexcept { ref_[I] = typeid_conversions::type_to_id(identity<Type>{}); return Type{}; } };
çŸåšãåºåé åãžã®ãã€ã³ã¿ãããããã®åºåé åã¯æãããååref_ãæã£ãŠããŸãããããã¯èµ·ãããŸããã æé»çãªåå€ææŒç®åãå€æŽãããŸããïŒtype_to_idé¢æ°ãåŒã³åºãããã«ãªããŸããã åãèå¥åã«å€æãããã®èå¥åãåºåé åref_ã«æžã蟌ã¿ãŸãã type_to_idã¡ãœããã®æãçæããããã«æ®ã£ãŠããŸãã ãã¯ãã䜿çšããŠãããè¡ããŸãã
#define BOOST_MAGIC_GET_REGISTER_TYPE(Type, Index) \ constexpr std::size_t type_to_id(identity<Type>) noexcept { \ return Index; \ } \ constexpr Type id_to_type( size_t_<Index > ) noexcept { \ Type res{}; \ return res; \ } \ /**/
ãã¯ãã¯ãtype_to_idé¢æ°ãçæããŸããããã«ãããã¿ã€ããèå¥åã«ãªããid_to_typeé¢æ°ãçæãããŸããããã«ãããèå¥åãã¿ã€ãã«æ»ããŸãã ãã®ãã¯ãã¯ãŠãŒã¶ãŒã«ã¯è¡šç€ºãããŸããã 䜿çšãããšããã«ãå®çŸ©ã解é€ããŸãã åºæ¬ã¿ã€ããç»é²ããŸãïŒãã¹ãŠãããã«ãªã¹ããããŠããããã§ã¯ãããŸããïŒïŒ
BOOST_MAGIC_GET_REGISTER_TYPE(unsigned char , 1) BOOST_MAGIC_GET_REGISTER_TYPE(unsigned short , 2) BOOST_MAGIC_GET_REGISTER_TYPE(unsigned int , 3) BOOST_MAGIC_GET_REGISTER_TYPE(unsigned long , 4) BOOST_MAGIC_GET_REGISTER_TYPE(unsigned long long , 5) BOOST_MAGIC_GET_REGISTER_TYPE(signed char , 6) BOOST_MAGIC_GET_REGISTER_TYPE(short , 7) BOOST_MAGIC_GET_REGISTER_TYPE(int , 8) BOOST_MAGIC_GET_REGISTER_TYPE(long , 9) BOOST_MAGIC_GET_REGISTER_TYPE(long long , 10) ...
ã€ãŸå ã䜿çšããŸããã çç±ã¯åŸã§èª¬æããŸãã ãã¹ãŠã®åºæ¬ã¿ã€ããç»é²ããŸããã ããã§ãåTããã®åTå ã®ãã£ãŒã«ãèå¥åã®é åã«å€æããé¢æ°ãäœæããŸããæãèå³æ·±ãã®ã¯ããã®é¢æ°ã®æ¬äœã§ãã
template <class T, std::size_t N, std::size_t... I> constexpr auto type_to_array_of_type_ids(std::size_t* types) noexcept -> decltype(T{ ubiq_constructor<I>{}... }) { T tmp{ ubiq_val< I >{types}... }; return tmp; }
äžæå€æ°ã®åæåãéçŽããããã«ubiqã€ã³ã¹ã¿ã³ã¹ãæž¡ããŸãã ä»åã¯ãåºåé åãžã®ãã€ã³ã¿ãŒãä¿æããŸããããã§ãtypesã¯ãã£ãŒã«ãåã®èå¥åãæžã蟌ãåºåé åã§ãã ãã®è¡ã®åŸïŒäžæå€æ°ãåæåããåŸïŒãtypesåºåé åã¯åãã£ãŒã«ãã®åèå¥åãä¿åããŸãã type_to_array_of_type_idsé¢æ°ã¯constexprã§ããã€ãŸãããã¹ãŠãã³ã³ãã€ã«æ®µéã§äœ¿çšã§ããŸãã çŸäººïŒ èå¥åãåã«æ»ãå¿ èŠããããŸãã ããã¯æ¬¡ã®ããã«è¡ãããŸãã
template <class T, std::size_t... I> constexpr auto as_tuple_impl(std::index_sequence<I...>) noexcept { constexpr auto a = array_of_type_ids<T>(); // #0 return std::tuple< // #3 decltype(typeid_conversions::id_to_type( // #2 size_t_<a[I]>{} // #1 ))... >{}; }
ãŒãè¡ïŒããã§èå¥åã®é åãååŸããŸãã ããã§ãå€æ°aã®åã¯std ::é åã«äŒŒãŠããŸãããconstexpråŒã§äœ¿çšã§ããããã«åŒ·ãæ¡åŒµãããŠããŸãïŒã»ãšãã©ã®åé¡ãconstexprã«ããC ++ 17ã§ã¯ãªãC ++ 14ãããããïŒ std :: arrary fixedïŒã
1è¡ç®ã§ã¯ãé åã®èŠçŽ ããæŽæ°å®æ°ãäœæããŸãã ç©åå®æ°ã¯std :: Integral_constantã§ãæåã®ãã©ã¡ãŒã¿ãŒã¯size_t_ã§ã2çªç®ã®ãã©ã¡ãŒã¿ãŒã¯a [I]ã ãã§ãã size_t_ã¯å®£èšããšã€ãªã¢ã¹ã䜿çšããŠããŸãã 2è¡ç®ã§èå¥åãåã«å€æãã3è¡ç®ã§std :: tupleãäœæããŸãããã®ã¿ãã«ã®åèŠçŽ ã¯ãTæ§é å ã®ããŒã¿åãšå®å šã«äžèŽããŸãã ä»ãç§ãã¡ã¯éåžžã«æããªããšãããããšãã§ããŸãã ããšãã°ãreinterpret_castãŠãŒã¶ãŒæ§é ãtuple'uã«å€æŽããŸãã ãããŠãã¿ãã«ã®ããã«ãŠãŒã¶ãŒæ§é ãæ±ãããšãã§ããŸãã ãŸããããã¯å°ãåä»ã§ãïŒreinterpret_castã
ã³ãŒããå°ãåçŽåãããŠãããããã³ããŒããŠå®è¡ããããšããªãã§ãã ããã ããšãã°ãstd :: tupleã¯åŒæ°ã®äœæãšç Žæ£ã®é åºãèŠå¶ããŸãããäžéšã®å®è£ ã§ã¯ãåŒæ°ãæ«å°Ÿããå é ã«åæåããééã£ãé åºã§æ ŒçŽããŸãããã®ãããstd :: tupleã¯æ©èœããŸããã ããªãã¯èªåã§äœããªããã°ãªããŸããã
ããã«é²ã¿ãŸãããã ãã€ã³ã¿ãŒãã©ããããïŒå®æ°ãã€ã³ã¿ãŒãžã®ãã€ã³ã¿ãŒãintãžã®ãã€ã³ã¿ãŒãªã©ïŒ
type_to_idé¢æ°ããããŸãã std :: size_tãè¿ãããã®std :: size_tããã®ãããã®æã¯äœ¿çšããŸããã§ããã32åã®åºæ¬åã«ã®ã¿äœ¿çšããŸããã ãããã£ãŠããããã®ãããã䜿çšããŠããã€ã³ã¿ãŒã«é¢ããæ å ±ããšã³ã³ãŒãã§ããŸãã ããšãã°ããŠãŒã¶ãŒæ§é ã«unsigned charåã®ãã£ãŒã«ããããå Žåããã€ããªåœ¢åŒã§ã¯æ¬¡ã®ããã«ãªããŸãã
unsigned char c0; // 0b00000000 00000000 00000000 000 00001
æäžäœãããã«ã¯ãcharèå¥åãå«ãŸããŸãã ããã¯1ã€ã§ãããããã£ãŠããã¯ãã§å²ãåœãŠãŸããã unsigned charãã€ã³ã¿ãŒãããå Žåãæäžäœãããã«ã¯ããããã€ã³ã¿ãŒã§ãããšããæ å ±ãæ ŒçŽãããŸãã
unsigned char* 1; // 0b 001 00000 00000000 00000000 000 00001
å®æ°ãã€ã³ã¿ãŒãããå Žåãæäžäœãããã«ã¯ããããå®æ°ãã€ã³ã¿ãŒã§ãããšããæ å ±ãæ ŒçŽãããŸãã
const unsigned char* 2; // 0b 010 00000 00000000 00000000 000 00001
è¿œå ã®ã€ã³ããã¯ã¹ã¬ãã«ïŒå¥ã®ãã€ã³ã¿ãŒïŒãè¿œå ãããšãä»ã®æäžäœããããå€æŽããããã€ã³ã¿ãŒããããšããæ å ±ãæ ŒçŽãããŸãã
const unsigned char** 3; // 0b 010001 00 00000000 00000000 000 00001
åºã«ãªãåãå€æŽããŸããæäžäœãããã¯å€æŽããããæäžäœãããã«ã¯èå¥å7ãå«ãŸããããã«ãªããŸãããããã¯ãshortã§äœæ¥ããŠããããšãæå³ããŸãã
const short** s0; // 0b 010001 00 00000000 00000000 000 00111
åãèå¥åã«å€æããé¢æ°ãè¿œå ããŸãïŒããã«å¿ããŠãããã®ããããè¿œå ããŸãïŒã
template<class Type> constexpr std::size_t type_to_id(identity<Type*>) template<class Type> constexpr std::size_t type_to_id(identity<const Type*>) template<class Type> constexpr std::size_t type_to_id(identity<const volatile Type*>) template<class Type> constexpr std::size_t type_to_id(identity<volatile Type*>)
ãããŠãèå¥åãåã«æ»ãéé¢æ°ãè¿œå ããŸãã
template<std::size_t Index> constexpr auto id_to_type(size_t_<Index>, if_extension<Index, native_const_ptr_type> = 0) noexcept; template<std::size_t Index> constexpr auto id_to_type(size_t_<Index>, if_extension<Index, native_ptr_type> = 0) noexcept; template<std::size_t Index> constexpr auto id_to_type(size_t_<Index>, if_extension<Index, native_const_volatile_ptr_type> = 0) noexcept; template<std::size_t Index> constexpr auto id_to_type(size_t_<Index>, if_extension<Index, native_volatile_ptr_type> = 0) noexcept;
ããã§ãif_extensionã¯std :: enable_ifã§ããããšã€ãªã¢ã¹ãšå€ãã®éæ³ããããŸãã éæ³ã¯ãèå¥åã«å¿ããŠãæ瀺ãããé¢æ°ã®1ã€ã ããåŒã³åºãããšãã§ãããšããããšã§ãã
enum'amiãã©ãããã°ããã®ãããããŸããã ç§ãæãã€ããå¯äžã®ããšã¯ãstd ::æ ¹æ¬çãªã¿ã€ããåŒã³åºãããšã§ããã ã€ãŸããåæåã®çš®é¡ã«é¢ããæ å ±ã倱ã£ãŠããŸãããã¹ãŠã®ãŠãŒã¶ãŒåæåãåºæ¬åã®ãªã¹ãã«ç»é²ããããšã¯ã§ããŸãããããã¯åã«äžå¯èœã§ãã 代ããã«ããã®åæåã®æ ŒçŽæ¹æ³ã®ã¿ããšã³ã³ãŒãããŸãã intã®å ŽåãintãšããŠä¿åããŸãããŠãŒã¶ãŒãclass enumïŒcharãæå®ããå ŽåãcharãååŸããŠcharã®ã¿ããšã³ã³ãŒãããenumã®ã¿ã€ãã«é¢ããæ å ±ã¯å€±ãããŸãã
è€éãªæ§é ãšã¯ã©ã¹ã«ãåãåé¡ããããŸãããã¹ãŠãåºæ¬åã®ãªã¹ãã«ç»é²ããããšã¯ã§ããŸããã ãããã£ãŠãã¯ã©ã¹å ãããäžåºŠèŠãŠããã®ã¯ã©ã¹ã«ãããã¹ãŠã®ãã£ãŒã«ããããŒãã¬ãã«ã¯ã©ã¹ã«ãããã®ããã«ãšã³ã³ãŒãããŸãã
æ§é aããããåãæ§é bã§ãããã£ãŒã«ãããããbã®äžãèŠãŠããã¹ãŠã®ãã£ãŒã«ããbããaã«ãã©ãã°ãããšããŸãã åçŽåïŒã¢ã©ã€ã¡ã³ãã«ã¯ãŸã å€ãã®ããžãã¯ããããå£ããªãããã«ããŠããŸãã
ããã¯æ¬¡ã®ããã«è¡ãããŸãïŒtype_to_idé¢æ°ã1ã€è¿œå ãããŸãïŒ
template <class Type> constexpr auto type_to_id(identity<Type>, typename std::enable_if< !std::is_enum<Type>::value && !std::is_empty<Type>::value>::type*) noexcept { return array_of_type_ids<Type>(); // Returns array! }
ä»åã¯é åãè¿ãããšãã§ããŸãïŒéå»ã®ãã®ã¯ãã¹ãŠsize_tãè¿ããŸããïŒã ubiqæ§é ãå€æŽããŠãé åãæäœãããªãã»ããã決å®ããæ¹æ³ã«ããžãã¯ãè¿œå ãããªãã»ãããæžã蟌ãå Žæãããã³äœæ¥ããŠããéšåæ§é ã«é¢ããæ å ±ãè¿œå ããå¿ èŠããããŸãã ããã¯ãã¹ãŠé·ããããŸãé¢çœããããŸããããããã©ããªããã«ã€ããŠã®äŸãããã€ããããŸãããããããæè¡çãªè©³çŽ°ã§ãã
ããã¯ç§ãã¡ã«äœãäžããããã¯ãã¹ãŠã©ãã§äœ¿çšã§ããŸããïŒ ããããããããã¹ãŠå®è£ ããæ¢è£œã®ã©ã€ãã©ãªãããããããããèªåã§èšè¿°ããå¿ èŠã¯ãããŸããã ãã®ã©ã€ãã©ãªãæäŸãããã®ã次ã«ç€ºããŸãã
ãŸãã æ¯èŒ ïŒæåã§æ¯èŒãèšè¿°ããå¿ èŠããªããªããŸãã
PODæ§é ã 3ã€ã®æ¹æ³ããããŸãã ã€ãŸãããŸã£ããäœãèšè¿°ããã«ã1ã€ã®ããããŒãã¡ã€ã«ãæ¥ç¶ããã ãã§ããã¹ãŠã®PODæ§é ã«ã€ããŠãããã«æ¯èŒã§ããŸãã
ç°çš®æ¯èŒããããŸããåããã£ãŒã«ããæã€2ã€ã®æ§é ãæã€ããšãã§ããŸããã
ããŸããŸãªã¿ã€ãã®ããŒã¿ãäºãã«æ¯èŒããŸãã
æ®éçãªããã·ã¥é¢æ°ããããŸã ïŒãŠãŒã¶ãŒæ§é ãããã«æž¡ããããããã®ããã·ã¥ãèæ ®ããŸãã
I / OæŒç®å ïŒå°å ¥éšã§ãã§ã«èŠããã®ããã¹ãŠæã£ãŠãããåäœããŸãã
ãã®ã¡ã¿ããã°ã©ã ã®éæ³ã«ã€ããŠåããŠè©±ãããšããéã®äžéšã®éçºè ã¯ãšãŠã幞ãã§ããïŒèŠããŠããªãã ãã§ãïŒã 圌ãã¯ãç°ãªããããã³ã«ãè¡šã1000ã®ç°ãªãå¹³é¢æ§é ãæã£ãŠãããšèšããŸãã ã€ãŸãã1察1ã®æ§é ããããã³ã«ã«ããããããŸãã ãããã®åæ§é ã«ã¯ã3ã€ã®ã·ãªã¢ã©ã€ã¶ãŒããããŸãïŒå°æ¥äœ¿çšãããããŒããŠã§ã¢ãšã¯ã€ã€ã«ãã£ãŠç°ãªããŸãïŒã ãŸãã3,000åã®ã·ãªã¢ã©ã€ã¶ãŒããããŸãã 圌ãã¯ããã«ãšãŠãäžæºã§ããã ãã®ã©ã€ãã©ãªã䜿çšããŠã3,000ã®ã·ãªã¢ã©ã€ã¶ãŒã3ã€ã®ã·ãªã¢ã©ã€ã¶ãŒã«ç°¡çŽ åããããšãã§ããŸããã 圌ãã¯ãšãŠã幞ãã§ããã
ãããã®ã¡ã¿ããã°ã©ãã³ã°ããªãã¯ã«ãããåºæ¬çãªãªãã¬ã¯ã·ã§ã³ã®å¯èœæ§ãéãããŸããããšãã°ãis_continuous_layout <T>ãis_padded <T>ãhas_unique_object_representations <T>ã®ããã«ãæ°ããtype_traitsãèšè¿°ã§ããŸãïŒC ++ 17ã®ããã«ïŒã
ã©ã€ãã©ãªã«ã¯ãªãçŽ æŽãããé¢æ°punch_hole <TãIndex>ãèšè¿°ãããŠãŒã¶ãŒæ§é å ã®æªäœ¿çšã®ããããšãã€ããå®çŸ©ããããããžã®ãªã³ã¯ãè¿ããä»ã®äººã䜿çšã§ããããã«ããããšãã§ããŸãã
æåŸã«ãããäžè¬åãããã¢ã«ãŽãªãºã ãæžãããšãã§ããŸãïŒããšãã°ãboost :: spiritã¯ãŠãŒã¶ãŒæ§é ã«ããã«è§£æãããããã«å€æŽã§ããboost :: fusionããã³boost :: spiritã®ãã¯ãã䜿çšããŠãã®æ§é ã宣èšããå¿ èŠã¯ãããŸãããã¡ãªã¿ã«ãããŒã¹ã::ã¹ããªããéçºè ã®1人ãç§ã®ãšããã«æ¥ãŠèšã£ããç§ã¯ãã®ããšãæãã§ããŸããå³æžé€šãžã®ãªã³ã¯ããã ãããã圌ã«ãããã
ããã€ãã®äŸããã®ãããªæãããæ§é ããããŸãïŒ
namespace foo { struct comparable_struct { int i; short s; char data[50]; bool bl; int a,b,c,d,e,f; }; } // namespace foo std::set<foo::comparable_struct> s;
ããããã®ãã£ãŒã«ãããããŸããåé¡ã¯ããã®æ§é ãäœããã®ã³ã³ããã«è»¢éããããšããããšã§ããããšãã°ãstd :: setã®å Žåãã©ã€ãã©ãªããªããã°ããã®æ§é ã«å¯ŸããŠæãããã³ã³ãã¬ãŒã¿ãäœæããå¿ èŠããããŸããstd :: tieã䜿çšããŠã³ã³ãã¬ãŒã¿ãŒãäœæã§ããŸãããæ§é ãå€æŽãããå Žåãé©åãªå€æŽãè¡ãå¿ èŠããããã¹ãŠã®å ŽæãèŠããŠããå¿ èŠããããŸããå°çãèããªãã»ãããã ãã¹ãŠããã®ãŸãŸã©ã€ãã©ãªã§æ©èœããŸããæ§é ãååŸããstd :: setã«æŒã蟌ã¿ãŸãããã¹ãŠæ©èœããŸãããã®æ§é ã®ã·ãªã¢ã«åãæ©èœããŸãã
std::set<foo::comparable_struct> s = { /* ... */ }; std::ofstream ofs("dump.txt"); for (auto& a: s) ofs << a << '\n';
äœãèããã«ãã ã®ã¹ããªãŒã ãã©ã€ãå€æ°ã§ã
éã·ãªã¢ã«åãæ©èœããŸãããã ã¹ããªãŒã ãããå€ãæ§é ã«æ»ãã䜿çšããã³ã³ããã«æ¿å ¥ããŸãã
std::set<foo::comparable_struct> s; std::ifstream ifs("dump.txt"); foo::comparable_struct cs; while (ifs >> cs) { char ignore = {}; ifs >> ignore; s.insert(cs); }
çŸããïŒæå°éã®ã³ãŒãã
ç§ã®ãæ°ã«å ¥ãã®äŸã¯ãæãæå³ã®ãªããã®ã§ãããèŠãç®ãçŸããããã§ããé¢æ°flat_tieïŒstd :: tupleããæ§é ãåæåã§ããŸãã
template <class T> auto flat_tie(T& val) noexcept; struct my_struct { int i, short s; }; my_struct s; flat_tie(s) = std::tuple<int, short>{10, 11};
ããã§ãmy_struct :: iã¯å€10ãä¿åããmy_struct :: sã¯sæ§é å ã«11ãä¿åããŸãã
ãããã£ãŠãçŸæç¹ã§ã¯ãããçš®ã®ãªãã¬ã¯ã·ã§ã³ãå®è¡ã§ããã©ã€ãã©ãªããããŸãããC ++ 14ã§åäœãã䜿çšã§ããå Žæã®äŸã§ãã
ãã ããã©ã€ãã©ãªã¯reinterpret_castã䜿çšããŸãããããŠãç§ã¯reinterpret_castsã奜ãã§ã¯ãããŸããããããã¯constexpré¢æ°ãèš±å¯ããããããevenãã§ãã
ãããä¿®æ£ããŠã¿ãŸãããããããè¿ éãã€ç°¡åã«ä¿®æ£ããŸãïŒåã¡ã¬ãã€ãã®ã³ãŒãã«å ¥ãã ãã§ããããã¯C ++ 17ã§è¡ããŸããèãæ¹ã¯æ¬¡ã®ãšããã§ããC++ 17ã§ã¯ãæ§é ãã€ã³ãã£ã³ã°ãè¿œå ãããŸãããããã¯ãæ§é ããã£ãŒã«ãã«å解ãããã£ãŒã«ããžã®ãªã³ã¯ãååŸã§ããããã«ãããã®ã§ããå¯äžã®åé¡ã¯ãæ§é å ã®ãã£ãŒã«ãã®æ°ãæ£ç¢ºã«ç¥ãå¿ èŠãããããšã§ããããããªããšããã¹ãŠãåéããããenable_ifãä»ããŠãã®æ§é ãã€ã³ãã£ã³ã°ã䜿çšããããšãã§ããŸãããããããèšäºã®åé ã§ãæ§é å ã®ãã£ãŒã«ãæ°ãååŸããæ¹æ³ãæ¢ã«åŠã³ãŸããããã£ãŒã«ãã®æ°ããããŒã¿åãäœæããã¿ã°ãã£ã¹ãããã䜿çšããŸãã
template <class T> constexpr auto as_tuple(T& val) noexcept { typedef size_t_<fields_count<T>()> fields_count_tag; return detail::as_tuple_impl(val, fields_count_tag{}); }
äžé£ã®as_tuple_implé¢æ°ãçæããŸãã
template <class T> constexpr auto as_tuple_impl(T&& val, size_t_<1>) noexcept { auto& [a] = std::forward<T>(val); return detail::make_tuple_of_references(a); } template <class T> constexpr auto as_tuple_impl(T&& val, size_t_<2>) noexcept { auto& [a,b] = std::forward<T>(val); return detail::make_tuple_of_references(a,b); }
ãããã®é¢æ°as_tuple_implã®å Žåã2çªç®ã®ãã©ã¡ãŒã¿ãŒã¯æ§é Tå ã®ãã£ãŒã«ãæ°ã§ããæ§é Tå ã«1ã€ã®ãã£ãŒã«ãããããšå€æããå Žåãæåã®é¢æ°as_tuple_implãåŒã³åºãããŸãã圌女ã¯æ§é ãã€ã³ãã£ã³ã°ã䜿çšããæåã®ãã£ãŒã«ããååŸãããã®ãã£ãŒã«ããžã®ãªã³ã¯ãããã¿ãã«ãäœæãããã®ã¿ãã«ããŠãŒã¶ãŒã«è¿ããŸããæ§é å ã«2ã€ã®ãã£ãŒã«ããããå Žåã2ã€ã®ãã£ãŒã«ãã«å¯ŸããŠæ§é ãã€ã³ãã£ã³ã°ãåŒã³åºããŸããããã¯2çªç®ã®é¢æ°ã§ãããŠãŒã¶ãŒãæ§é çã«ãã£ãŒã«ãaãšbã«å解ããæåã®ãã£ãŒã«ããš2çªç®ã®ãã£ãŒã«ããžã®ãªã³ã¯ãæ ŒçŽããã¿ãã«ãè¿ããŸããçŸäººïŒ
æè¯ã®éšåã¯ããã®ãã¹ãŠãconstexprã§ãããã«ã¹ã¿ã ãã£ãŒã«ããšã«ã¹ã¿ã æ§é ã§åäœããstd :: getãèšè¿°ã§ããããšã§ããããã¯ãã¹ãŠã³ã³ãã€ã«æ®µéã§è¡ãããŸããä¿¡ããããªãã»ã©ã®çŸãããå¯äžã®åé¡ã¯ãæ§é ãã€ã³ãã£ã³ã°ãæã€ã³ãŒãããŸã ãã¹ããããŠããªãããšã§ããã³ã³ãã€ã©ã¯ãŸã æ§é ãã€ã³ãã£ã³ã°ããµããŒãããŠããŸããããããã£ãŠãããã¯çŸããçè«ã§ããããããã2ã3ã®å€æŽã§æ©èœããŸãã
ã¢ã³ãã³ã«ãã£ãŠå ã®ã¬ããŒãantoshkka Polukhina - https://youtu.be/jDI5CHKFKd0
å³æžé€šæ£ç¢ºãã€ãã©ãããªãã¬ã¯ã·ã§ã³ïŒmagic_getïŒ