рдХрднреА-рдХрднреА рд╣рдо рдРрд╕реЗ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ рдЬрд┐рдирдХрд╛ рдореВрд▓реНрдп рдЕрддреНрдпрдзрд┐рдХ рд╕рдВрджрд┐рдЧреНрдз рд╣реИред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдРрд╕рд╛ рд╣реА рд╣реИред
рдХреЛрдб рдПрдХ рд╣рдЬрд╛рд░ рд╢рдмреНрджреЛрдВ рд╕реЗ рдмреЗрд╣рддрд░ рд╣реИ
рдореИрдВ рдкреВрдВрдЫ рд╕реЗ рдмрд┐рд▓реНрд▓реА рдХреЛ рдирд╣реАрдВ рдЦреАрдВрдЪреВрдВрдЧрд╛, рд▓реЗрдХрд┐рди рдореИрдВ рд╕реАрдзреЗ рдмрд┐рдВрджреБ рдкрд░ рдЬрд╛рдКрдВрдЧрд╛ред рдЖрдорддреМрд░ рдкрд░ рд╣рдо рдЗрд╕ рддрд░рд╣ рд╕реЗ
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*);
рдЕрдм,
f()
рдХреА рдШреЛрд╖рдгрд╛ рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП, рд╣рдо рд╕рд╣рдЬ рд░реВрдк рд╕реЗ рд╕рдордЭрддреЗ рд╣реИрдВ рдХрд┐ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкрд░рд╡рд╛рд╣ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЙрд╕рдХреЗ рддрд░реНрдХ рдореЗрдВ рдХреНрдпрд╛ рдЯреИрдЧ рд╣реИред
рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ
Base
рдХреНрд▓рд╛рд╕ рдореЗрдВ, рдПрдХ рдлреНрд░реЗрдВрдб рдлрдВрдХреНрд╢рди рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рдПрдХ рдЯреИрдЧ рдХреЛ рд▓реМрдЯрд╛рддрд╛ рд╣реИ рдФрд░ рдПрдХ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╣реИред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдЬрдм рд╣рдо рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП,
Foo
, рд╣рдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕реА рдорд╛рдорд▓реЗ рдореЗрдВ рдЗрд╕реА рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рдХреЗ рд╕рд╛рде рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рддреЗ рд╣реИрдВ:
void get_tag(Foo*);
рдЬрдм рд╣рдо рдЯреЗрдореНрдкрд▓реЗрдЯ (рдЯреЗрдореНрдкрд▓реЗрдЯ рддрд╛рддреНрдХрд╛рд▓рд┐рдХрддрд╛) рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рддреЗ рд╕рдордп
f()
рдХрд╣рддреЗ рд╣реИрдВ, рддреЛ рдХрдВрдкрд╛рдЗрд▓рд░ рдлрд╝рдВрдХреНрд╢рди рддрд░реНрдХ рдХреЗ рд▓рд┐рдП рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдЯреЗрдореНрдкрд▓реЗрдЯ рддрд░реНрдХ (рдЬреЛ
Foo
рдХрдХреНрд╖рд╛ рдХрд╛ рдПрдХ рдЙрджреНрджреЗрд╢реНрдп рд╣реИ) рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реИ:
- рд╕рдВрдХрд▓рдХ рдХреЛ
base_tag
рдЯреЗрдореНрдкрд▓реЗрдЯ рдЙрджрд╛рд╣рд░рдг рд╕реЗ рдЯреИрдЧ рдкреНрд░рдХрд╛рд░ рдорд┐рд▓рддрд╛ рд╣реИ, - рдмрджрд▓реЗ рдореЗрдВ,
get_tag()
рджреНрд╡рд╛рд░рд╛ рд▓реМрдЯрд╛рдП рдЧрдП рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ get_tag()
, рдПрдХ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рд╕реВрдЪрдХ Foo*
рд╕рд╛рде, - рдЬреЛ рдУрд╡рд░рд▓реЛрдб рд░реЗрдЬреЛрд▓реНрдпреВрд╢рди рдореИрдХреЗрдирд┐рдЬреНрдо рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░рддрд╛ рд╣реИ рдФрд░
Base
рдХреНрд▓рд╛рд╕ рдореЗрдВ рдШреЛрд╖рд┐рдд рдХрд┐рдП рдЧрдП рдлрдВрдХреНрд╢рди рдХреЛ Foo
рдФрд░ void
рд╕рд╛рде рдЯреЗрдореНрдкреНрд▓реЗрдЯ рддрд░реНрдХреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рджреЗрддрд╛ рд╣реИ, рдпрд╛рдиреА Base<Foo, void>
- ???
- рд▓рд╛рдн!
рдпрд╣реА рд╣реИ, рд╕рд░реНрдХрд▓ рдмрдВрдж рд╣реИ!
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);
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐
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*);
рдКрдкрд░ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рд╕рдорддреБрд▓реНрдп рд╣реИ
struct Foo : Base<Foo, void> {};
рддреЛ рдЕрдм рд╣рдо рдорд╛рди рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХреЛрдИ рдЯреИрдЧ рдирд╣реАрдВ рд╣реИ рдФрд░ рдЙрдиреНрдирдд рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдЫреЛрдбрд╝ рджреЗрдВред
C ++ 98 рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛?
рдкреБрд░рд╛рдиреЗ рдХрдВрдкрд╛рдЗрд▓рд░
decltype
рдХреАрд╡рд░реНрдб рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЖрдкрдХреЗ рдкрд╛рд╕ рдЯреИрдЧреНрд╕ рдХреА рд╕реАрдорд┐рдд рд╕рдВрдЦреНрдпрд╛ (рдпрд╛ рдЬреЛ рдХреБрдЫ рднреА) рд╣реИ, рддреЛ рдЖрдк рдЯреНрд░рд┐рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ
sizeof
(
sizeof
рдЪрд╛рд▓) рдХреЗ рд╕рд╛рде рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
struct tag1 {};
рдереЛрдбрд╝рд╛ рдХреНрд░рд┐рдпрд╛, рд▓реЗрдХрд┐рди рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рд╢рд░реАрд░ рдХреА рдЕрддрд┐рд░рд┐рдХреНрдд рд╣рд▓рдЪрд▓реЗрдВ?
рддреЛ рдХреНрдпрд╛ рдпреЗ рд╕рдм рдЕрддрд┐рд░рд┐рдХреНрдд рдЗрд╢рд╛рд░реЗ рд╣реИрдВ?
рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╣реА рджреЗрдЦрд╛ рд╣реИ рдХрд┐ рдпрд╣ рддрдХрдиреАрдХ рдХреЛрдб рдХреЛ рдереЛрдбрд╝рд╛ рдФрд░ рд╕реБрдВрджрд░ рдмрдирд╛рддреА рд╣реИред рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рджреЛ рддрд░реНрдХреЛрдВ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИред рдмреЗрд╢рдХ, рд╣рдо рдЗрд╕ рддрд░рд╣ рдХреЛрдб рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ:
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
". , (, ), . , , . , , .
, , - .