рдЕрдЪреНрдЫреЗ рдкреБрд░рд╛рдиреЗ CRTP рдирдИ рдЯреНрд░рд┐рдХреНрд╕ рд╕реАрдЦреЗрдВ

рдХрднреА-рдХрднреА рд╣рдо рдРрд╕реЗ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ рдЬрд┐рдирдХрд╛ рдореВрд▓реНрдп рдЕрддреНрдпрдзрд┐рдХ рд╕рдВрджрд┐рдЧреНрдз рд╣реИред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдРрд╕рд╛ рд╣реА рд╣реИред

рдХреЛрдб рдПрдХ рд╣рдЬрд╛рд░ рд╢рдмреНрджреЛрдВ рд╕реЗ рдмреЗрд╣рддрд░ рд╣реИ


рдореИрдВ рдкреВрдВрдЫ рд╕реЗ рдмрд┐рд▓реНрд▓реА рдХреЛ рдирд╣реАрдВ рдЦреАрдВрдЪреВрдВрдЧрд╛, рд▓реЗрдХрд┐рди рдореИрдВ рд╕реАрдзреЗ рдмрд┐рдВрджреБ рдкрд░ рдЬрд╛рдКрдВрдЧрд╛ред рдЖрдорддреМрд░ рдкрд░ рд╣рдо рдЗрд╕ рддрд░рд╣ рд╕реЗ CRTP рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ:
template<typename type, typename tag> struct Base {}; template<typename type, typename tag> void f(const Base<type, tag>&) {} struct Foo : Base<Foo, void> {}; int main() { Foo foo; f(foo); } 

f() рдлрд╝рдВрдХреНрд╢рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкрд░рд╡рд╛рд╣ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдЙрд╕рдХреЗ рддрд░реНрдХ рдореЗрдВ рдХреНрдпрд╛ рдЯреИрдЧ рд╣реИ, рдФрд░ рдпрд╣ Base рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓реА рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░ рдХреА рд╡рд╕реНрддреБ рд▓реЗрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рдпрд╣ рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдирд╣реАрдВ рд╣реЛрдЧрд╛ рдпрджрд┐ рд╣рдо рдХреЗрд╡рд▓ рдЙрд╕ рдЯреИрдЧ рдХреЛ рдЫреЛрдбрд╝ рджреЗрдВ рдЬреЛ рд╣рдореЗрдВ рд░реБрдЪрд┐рдХрд░ рдирд╣реАрдВ рд╣реИ? рдЗрд╕реЗ рджреЗрдЦреЗрдВ:
 template<typename t> struct base_tag { typedef decltype(get_tag((t*)42)) type; }; template<typename type, typename tag = typename base_tag<type>::type> struct Base { friend tag get_tag(type*); //never defined }; template<typename type> void f(const Base<type>&) {} struct Foo : Base<Foo, void> {}; int main() { Foo foo; f(foo); } 

рдЕрдм, f() рдХреА рдШреЛрд╖рдгрд╛ рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП, рд╣рдо рд╕рд╣рдЬ рд░реВрдк рд╕реЗ рд╕рдордЭрддреЗ рд╣реИрдВ рдХрд┐ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкрд░рд╡рд╛рд╣ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЙрд╕рдХреЗ рддрд░реНрдХ рдореЗрдВ рдХреНрдпрд╛ рдЯреИрдЧ рд╣реИред

рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ


Base рдХреНрд▓рд╛рд╕ рдореЗрдВ, рдПрдХ рдлреНрд░реЗрдВрдб рдлрдВрдХреНрд╢рди рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рдПрдХ рдЯреИрдЧ рдХреЛ рд▓реМрдЯрд╛рддрд╛ рд╣реИ рдФрд░ рдПрдХ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╣реИред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдЬрдм рд╣рдо рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, Foo , рд╣рдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕реА рдорд╛рдорд▓реЗ рдореЗрдВ рдЗрд╕реА рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рдХреЗ рд╕рд╛рде рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рддреЗ рд╣реИрдВ:
 void get_tag(Foo*); 


рдЬрдм рд╣рдо рдЯреЗрдореНрдкрд▓реЗрдЯ (рдЯреЗрдореНрдкрд▓реЗрдЯ рддрд╛рддреНрдХрд╛рд▓рд┐рдХрддрд╛) рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рддреЗ рд╕рдордп f() рдХрд╣рддреЗ рд╣реИрдВ, рддреЛ рдХрдВрдкрд╛рдЗрд▓рд░ рдлрд╝рдВрдХреНрд╢рди рддрд░реНрдХ рдХреЗ рд▓рд┐рдП рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдЯреЗрдореНрдкрд▓реЗрдЯ рддрд░реНрдХ (рдЬреЛ Foo рдХрдХреНрд╖рд╛ рдХрд╛ рдПрдХ рдЙрджреНрджреЗрд╢реНрдп рд╣реИ) рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реИ:
  1. рд╕рдВрдХрд▓рдХ рдХреЛ base_tag рдЯреЗрдореНрдкрд▓реЗрдЯ рдЙрджрд╛рд╣рд░рдг рд╕реЗ рдЯреИрдЧ рдкреНрд░рдХрд╛рд░ рдорд┐рд▓рддрд╛ рд╣реИ,
  2. рдмрджрд▓реЗ рдореЗрдВ, get_tag() рджреНрд╡рд╛рд░рд╛ рд▓реМрдЯрд╛рдП рдЧрдП рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ get_tag() , рдПрдХ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рд╕реВрдЪрдХ Foo* рд╕рд╛рде,
  3. рдЬреЛ рдУрд╡рд░рд▓реЛрдб рд░реЗрдЬреЛрд▓реНрдпреВрд╢рди рдореИрдХреЗрдирд┐рдЬреНрдо рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░рддрд╛ рд╣реИ рдФрд░ Base рдХреНрд▓рд╛рд╕ рдореЗрдВ рдШреЛрд╖рд┐рдд рдХрд┐рдП рдЧрдП рдлрдВрдХреНрд╢рди рдХреЛ Foo рдФрд░ void рд╕рд╛рде рдЯреЗрдореНрдкреНрд▓реЗрдЯ рддрд░реНрдХреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рджреЗрддрд╛ рд╣реИ, рдпрд╛рдиреА Base<Foo, void>
  4. ???
  5. рд▓рд╛рдн!

рдпрд╣реА рд╣реИ, рд╕рд░реНрдХрд▓ рдмрдВрдж рд╣реИ!

ECRTP


рдХреБрдЫ рднреА рдмреЗрд╣рддрд░ рдЖрд╡рд┐рд╖реНрдХрд╛рд░ рдХрд┐рдП рдмрд┐рдирд╛, рдореИрдВ рдЗрд╕реЗ "рдЕрддреНрдпрдзрд┐рдХ рдЙрддреНрд╕реБрдХрддрд╛рдкреВрд░реНрд╡рдХ рдЖрд╡рд░реНрддреА рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреИрдЯрд░реНрди" рдХрд╣рддрд╛ рд╣реВрдВред рддреЛ рдпрд╣ рдФрд░ рдХреНрдпрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ?

рдпрджрд┐ рд╣рдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдпрд╣ рдЪрд╛рд╣рддреЗ рд╣реИрдВ , рддреЛ рдЯреИрдЧ рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
 template<typename type> void g(const Base<type, int>&) {} struct Bar : Base<Bar, int> {}; int main() { Foo foo; Bar bar; f(foo); f(bar); g(foo); //doesn't compile by design g(bar); } 


рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ g(foo) рдЬрд╛рдирдмреВрдЭрдХрд░ рдХреЛрдб рд╕рдВрдХрд▓рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐ рддрд░реНрдХ рдЯреИрдЧ рдХрд╛ рдкреНрд░рдХрд╛рд░ int рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП (рдЬрдмрдХрд┐ рдпрд╣ Foo рдХрд╛ void рдкреНрд░рдХрд╛рд░ рд╣реИ)ред рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдХрдВрдкрд╛рдЗрд▓рд░ рдПрдХ рд╕реБрдВрджрд░ рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред рдЦреИрд░, рдХрдо рд╕реЗ рдХрдо MSVC10 рдФрд░ GCC4.7ред

MSVC10
 main.cpp (30): рддреНрд░реБрдЯрд┐ C2784: 'рд╢реВрдиреНрдп рдЬреА (рдХреЙрдиреНрд╕реНрдЯреЗрдВрдЯ рдмреЗрд╕ <рдЯрд╛рдЗрдк, int> &)': рдЯреЗрдореНрдкреНрд▓реЗрдЯ рддрд░реНрдХ рд╡рд┐рддрд░реНрдХ рдирд╣реАрдВ рдХрд░ рд╕рдХрд╛
           'рдлрд╝реВ' рд╕реЗ 'рдХрд╛рд╕реНрдЯ рдмреЗрд╕ <рдкреНрд░рдХрд╛рд░, int> &' рдХреЗ рд▓рд┐рдП
           main.cpp (18): 'рдЬреА' рдХреА рдШреЛрд╖рдгрд╛ рджреЗрдЦреЗрдВ

GCC4.7
 source.cpp: рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ 'int main ()':
 source.cpp: 30: 8: рддреНрд░реБрдЯрд┐: 'g тАЛтАЛ(Foo &)' рдкрд░ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдореЗрд▓ рдирд╣реАрдВ рдЦрд╛рддрд╛
 source.cpp: 30: 8: рдиреЛрдЯ: рдЙрдореНрдореАрджрд╡рд╛рд░ рд╣реИ:
 source.cpp: 18: 6: рдиреЛрдЯ: рдЯреЗрдореНрдкреНрд▓реЗрдЯ <рд╡рд░реНрдЧ рдкреНрд░рдХрд╛рд░> рд╢реВрдиреНрдп рдЬреА (рдХрд╛рд╕реНрдЯ рдмреЗрд╕ <рдкреНрд░рдХрд╛рд░, рдЗрдВрдЯ> &)
 source.cpp: 18: 6: рдиреЛрдЯ: рдЯреЗрдореНрдкрд▓реЗрдЯ рддрд░реНрдХ рдХрдЯреМрддреА / рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рд╡рд┐рдлрд▓:
 source.cpp: 30: 8: рдиреЛрдЯ: рдмреЗрдореЗрд▓ рдкреНрд░рдХрд╛рд░ 'int' рдФрд░ 'void'
 source.cpp: 30: 8: рдиреЛрдЯ: 'рдлреВ' 'рдЖрдзрд╛рд░ рдмреЗрд╕ <рдЯрд╛рдЗрдк, рдЗрдВрдЯ> рд╕реЗ рд╡реНрдпреБрддреНрдкрдиреНрди рдирд╣реАрдВ рд╣реИ'
MSVC рд╕реЗ рднреА рдмреЗрд╣рддрд░!


рдЖрдк рдПрдХ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдЯреИрдЧ рднреА рд╕реЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
 template<typename type> void get_tag(type*); //default tag is 'void' template<typename t> struct base_tag { typedef decltype(get_tag((t*)42)) type; }; template<typename type, typename tag = typename base_tag<type>::type> struct Base { friend tag get_tag(type*); //never defined }; struct Foo : Base<Foo> //tag defaults to void {}; 


рдКрдкрд░ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рд╕рдорддреБрд▓реНрдп рд╣реИ
 struct Foo : Base<Foo, void> {}; 


рддреЛ рдЕрдм рд╣рдо рдорд╛рди рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХреЛрдИ рдЯреИрдЧ рдирд╣реАрдВ рд╣реИ рдФрд░ рдЙрдиреНрдирдд рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдЫреЛрдбрд╝ рджреЗрдВред

C ++ 98 рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛?


рдкреБрд░рд╛рдиреЗ рдХрдВрдкрд╛рдЗрд▓рд░ decltype рдХреАрд╡рд░реНрдб рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЖрдкрдХреЗ рдкрд╛рд╕ рдЯреИрдЧреНрд╕ рдХреА рд╕реАрдорд┐рдд рд╕рдВрдЦреНрдпрд╛ (рдпрд╛ рдЬреЛ рдХреБрдЫ рднреА) рд╣реИ, рддреЛ рдЖрдк рдЯреНрд░рд┐рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ sizeof ( sizeof рдЪрд╛рд▓) рдХреЗ рд╕рд╛рде рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
 struct tag1 {}; //a set of tags struct tag2 {}; struct tag3 {}; #define REGISTER_TAG(tag, id) char (&get_tag_id(tag))[id];\ template<> struct tag_by_id<id>\ { typedef tag type; }; template<unsigned> struct tag_by_id; REGISTER_TAG(tag1, 1) //defines id's REGISTER_TAG(tag2, 2) REGISTER_TAG(tag3, 42) template<typename t> struct base_tag { enum { tag_id = sizeof(get_tag_id(get_tag((t*)42))) }; typedef typename tag_by_id<tag_id>::type type; }; template<typename type, typename tag = typename base_tag<type>::type> struct Base { friend tag get_tag(type*); //never defined }; template<typename type> void f(const Base<type>&) {} struct Foo : Base<Foo, tag1> {}; int main() { Foo foo; f(foo); } 

рдереЛрдбрд╝рд╛ рдХреНрд░рд┐рдпрд╛, рд▓реЗрдХрд┐рди рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рд╢рд░реАрд░ рдХреА рдЕрддрд┐рд░рд┐рдХреНрдд рд╣рд▓рдЪрд▓реЗрдВ?


рддреЛ рдХреНрдпрд╛ рдпреЗ рд╕рдм рдЕрддрд┐рд░рд┐рдХреНрдд рдЗрд╢рд╛рд░реЗ рд╣реИрдВ?

рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╣реА рджреЗрдЦрд╛ рд╣реИ рдХрд┐ рдпрд╣ рддрдХрдиреАрдХ рдХреЛрдб рдХреЛ рдереЛрдбрд╝рд╛ рдФрд░ рд╕реБрдВрджрд░ рдмрдирд╛рддреА рд╣реИред рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рджреЛ рддрд░реНрдХреЛрдВ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИред рдмреЗрд╢рдХ, рд╣рдо рдЗрд╕ рддрд░рд╣ рдХреЛрдб рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ:
 template<class type1, class tag1, class type2, class tag2> void h(const Base<type1, tag1>&, const Base<type2, tag2>&) {} 

рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЫреЛрдЯреЗ class рдХреАрд╡рд░реНрдб рдХреЛрдб рдХреЛ рдмрд╣реБрдд рдЫреЛрдЯрд╛ рдирд╣реАрдВ рдмрдирд╛рддрд╛ рд╣реИред

рдЗрд╕рдХреЗ рд╕рд╛рде рддреБрд▓рдирд╛ рдХрд░реЗрдВ:
 template<class type1, class type2> void h(const Base<type1>&, const Base<type2>&) {} 

рдЯреИрдЧ? рдирд╣реАрдВ, рдореИрдВрдиреЗ рд╕реБрдирд╛ рдирд╣реАрдВ ...

рдЖрдк рд╕реНрд╡рдпрдВ рддреАрди рдпрд╛ рдЕрдзрд┐рдХ рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╢рд╛рдирджрд╛рд░ рд╕реНрдерд┐рддрд┐ рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рд╡рд┐рдЪрд╛рд░ рдпрд╣ рд╣реИ: рдпрджрд┐ рд╣рдо рдХрд┐рд╕реА рдирд┐рд╢реНрдЪрд┐рдд рдЪреАрдЬ рдореЗрдВ рд░реБрдЪрд┐ рдирд╣реАрдВ рд░рдЦрддреЗ рд╣реИрдВ, рддреЛ рдХреНрдпрд╛ рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд░реВрдк рд╕реЗ рд╕реНрдкрд╖реНрдЯ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП? рдЬрдм рдХреЛрдИ std::vector, ( ), " std::vector () std::allocator ". , (, ), . , , . , , .


, , - .
рд▓рд┐рдЦрддрд╛ рд╣реИ std::vector, ( ), " std::vector () std::allocator ". , (, ), . , , . , , .


, , - .
std::vector, ( ), " std::vector () std::allocator ". , (, ), . , , . , , .


, , - .

std::vector, ( ), " std::vector () std::allocator ". , (, ), . , , . , , .


, , - .

std::vector, ( ), " std::vector () std::allocator ". , (, ), . , , . , , .


, , - .

Source: https://habr.com/ru/post/In152387/


All Articles