рд╡рд┐рдХрд╛рд╕ рдФрд░ рдирд┐рд╖реНрдкрд╛рджрди рдХреА рдЧрддрд┐ C рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ

рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдФрд░ рдХреНрд░реЙрд╕-рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝реЗрд╢рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд▓реЗрдЦ рдХреА рдирд┐рд░рдВрддрд░рддрд╛ рдореЗрдВ, 5 рдлрд╝реАрд▓реНрдбреНрд╕ рдФрд░ 10,000,000 рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреА рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреВрд░реНрдг рдкрд╛рд╕ рдХреЗ рд╕рд╛рде рдЦреЛрдЬ рдХрд╛рд░реНрдп рдХреЗ рдЙрджрд╛рд╣рд░рдг рд╕реЗ, рдФрд░ рдЗрд╕ рдХрд╛рд░реНрдп рдХреА рдЕрдирд┐рд╡рд╛рд░реНрдпрддрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЗрдВрдбреЗрдХреНрд╕ рдЦреЛрдЬ рдХреЗ рд╕рд╛рде, рдореИрдВ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ рдХрд┐ 3.5-5.3 рдмрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдРрд╕реА рдЦреЛрдЬ рдХреЛ рдХреИрд╕реЗ рддреЗрдЬ рдХрд┐рдпрд╛ рдЬрд╛рдПред C ++ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ред
рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдореЗрдВ, рд╣рдордиреЗ рдЦреЛрдЬ рдХреЛ 1.3 рдЧреБрдирд╛ рдмрдврд╝рд╛рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣реЗ: GitHub.com
рд╣рдо рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд░реВрдк рд╕реЗ рднрд╛рд╖рд╛ рдирд┐рд░реНрдорд╛рдг рдХрд╛ рд╡рд░реНрдгрди рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдХрд╛рд░реНрдп рдХреЗ рдЪрд░рдгреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдХреЛ рд╣рд▓ рдХрд░рддреЗ рд╕рдордп C ++ рдХреЗ рдлрд╛рдпрджреЗ рдмрддрд╛рдПрдВрдЧреЗред
рд╣рдо рдЕрднреА рднреА MSVC11 (MSVS2012) рдФрд░ GCC 4.7.2 рдХреЗ рддрд╣рдд рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рдФрд░ рд╣рдо рдЙрдирдореЗрдВ C рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рд▓рд╛рдЧреВ рдорд╛рдирдХ C ++ 11ред
рд╕рдордЭ рдХреА рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рд╣рдо рдЕрднреА рднреА рд╕реВрдЪрдХрд╛рдВрдХ рдЦреЛрдЬ рдХреЗ рдмрд┐рдирд╛ рд▓рд┐рдЦ тАЛтАЛрд░рд╣реЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЗрд╕ рд╕рдорд╛рдзрд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдмрд╛рдж рдореЗрдВ рд╕реВрдЪрдХрд╛рдВрдХ рдЦреЛрдЬ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

1. рд╕реА ++ рдореЗрдВ рдХрдЯреНрдЯрд░ рд╕рдорд╛рдзрд╛рди


рдпрд╣ рд╕реА рдореЗрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХрдЯреНрдЯрд░ рд╕рдорд╛рдзрд╛рди рдХреА рддрд░рд╣ рджрд┐рдЦрддрд╛ рдерд╛ред рдЗрд╕рдХрд╛ рдХрд╛рд░рдг рдпрд╣ рд╣реИ рдХрд┐ рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ рд╕реА рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ 3840 рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдиреЗ рдФрд░ рдХрд╣реАрдВ рднреА рдХреЛрдИ рдЧрд▓рддреА рдирд╣реАрдВ рдХрд░рдиреА рд╣реИред рдЬрдмрдХрд┐ рд╕реА-рдбреЗрд╡рд▓рдкрд░реНрд╕ рдЙрдиреНрд╣реЗрдВ рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рд╣рдо рдЙрдиреНрд╣реЗрдВ рдмрд╣реБрдд рд╕рдореНрдорд╛рди рдХреЗ рд╕рд╛рде рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░реЗрдВрдЧреЗ, рдФрд░ рдореИрдВ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ рдХрд┐ рдХреИрд╕реЗ рд╕реА ++ рд╕рдВрдХрд▓рдХ рдЖрдкрдХреЗ рд▓рд┐рдП рдЗрди 3840 рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВред рд╡рд╣ рдЗрд╕реЗ рдЬрд▓реНрджреА рдирд╣реАрдВ рдХрд░реЗрдЧрд╛, рд▓реЗрдХрд┐рди рд╕реА-рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рддреЗрдЬреА рд╕реЗ рдФрд░ рдЕрдзрд┐рдХ рд╕рдЯреАрдХ рд░реВрдк рд╕реЗ рдкрд░рд┐рдорд╛рдг рдХреЗ рдЖрджреЗрд╢ рдЙрдиреНрд╣реЗрдВ рд▓рд┐рдЦреЗрдВрдЧреЗред
рдпрд╣ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ, рдбреАрдмреАрдПрдордПрд╕ рдХреЗ рд╕рд┐рджреНрдзрд╛рдВрдд рдореЗрдВ рдПрдХ рд╡рд┐рдзреЗрдп ( selectivity ) рдХреА рдЪрдпрдирд╛рддреНрдордХрддрд╛ рдЬреИрд╕реА рдХреЛрдИ рдЪреАрдЬ рд╣реИ - рдПрдХ рд╕реНрдерд┐рддрд┐ (рд╡рд┐рдзреЗрдп) рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдЙрдкрдпреБрдХреНрдд рддрд╛рд▓рд┐рдХрд╛ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХрд╛ рдкреНрд░рддрд┐рд╢рддред рд╕реНрдерд┐рддрд┐ рдХреА рдЪрдпрдирд╛рддреНрдордХрддрд╛ рдХрдо рд╣реИ, рдкрд╣рд▓реЗ рдЗрд╕рдХреА рддреБрд▓рдирд╛ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдФрд░ рдЬрд┐рддрдиреА рдЬрд▓реНрджреА рд╣рдо рдорд╣рд╕реВрд╕ рдХрд░реЗрдВрдЧреЗ рдХрд┐ рд░реЗрдЦрд╛ рдлрд┐рдЯ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИред рдпрд╛рдиреА рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рддреБрд▓рдирд╛ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдПрдВред
рд╡рд╛рд╕реНрддрд╡рд┐рдХ DBMS рдореЗрдВ, рдЗрд╕рдХреЗ рд▓рд┐рдП, рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝рд░ рдЖрдВрдХрдбрд╝реЗ рдПрдХрддреНрд░ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдбреЗрдЯрд╛ рд╡рд┐рддрд░рдг рдЕрдиреБрд╕реВрдЪреА рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдЪрдпрдирд╛рддреНрдордХрддрд╛ рдХреА рдЧрдгрдирд╛ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╕реВрддреНрд░ рдХрд╛ рдЪрдпрди рдХрд░рддрд╛ рд╣реИред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЦреЗрддреЛрдВ рдХреА рдЧрдгрдирд╛ рдХреЗ рд╕рд╛рде рдЕрд╕рддрдд рдЧрдгрд┐рдд рдФрд░ рдХреЙрдореНрдмрд┐рдиреЗрдЯрд░рд┐рдХреНрд╕ рдЖрдЬ рдЖрдкрдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП рд╣рдо рдбреЗрдЯрд╛ рдХреЗ рд╕рдорд╛рди рд╡рд┐рддрд░рдг рдХреА рдЧрдгрдирд╛ рд╕реЗ рдХрд╛рд░реНрдбрд┐рдиреИрд▓рд┐рдЯреА рдХреЗ рд▓рд┐рдП рдЪрдпрдирд╢реАрд▓рддрд╛ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред (рдХреЙрд▓рдо рдХреА рдХрд╛рд░реНрдбрд┐рдиреИрд▓рд┐рдЯреА рдХреЙрд▓рдо рдореЗрдВ рдЕрджреНрд╡рд┐рддреАрдп рдореВрд▓реНрдпреЛрдВ рдХрд╛ рдкреНрд░рддрд┐рд╢рдд рд╣реИред)
рдЪрдпрдирд╛рддреНрдордХрддрд╛ (рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛) рдХреЗ рдмрд░рд╛рдмрд░ рд╣реЛрдЧреА:
selectivity = c_array_size * (1 + field.end тАУ field.begin) / cardinality;
рд╕рд░рдгреА рдХрд╛ рдЖрдХрд╛рд░ рдФрд░ рд╕рдорд╛рди рд░реВрдк рд╕реЗ рд╡рд┐рддрд░рд┐рдд рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдбрд┐рдиреИрд▓рд┐рдЯреА рд╕рдВрдХрд▓рди рдЪрд░рдг рдореЗрдВ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЬрд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред рдФрд░ рд╣рдо рд░рдирдЯрд╛рдЗрдо рдкрд░ рдкреНрд░рддреНрдпреЗрдХ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рдЦреЛрдЬ рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдХреА рд╕реАрдорд╛рдПрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЪрдпрдирд╛рддреНрдордХрддрд╛ рдХреА рдЧрдгрдирд╛ рдХрд░рддреЗ рд╣реИрдВред
рдлрд┐рд░ рд╣рдо рдЫреЛрдЯреА рд╕реЗ рд╢реБрд░реВ рд╣реЛрдиреЗ рд╡рд╛рд▓реА рдЪрдпрдирд╛рддреНрдордХрддрд╛ рдмрдврд╝рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЦреЗрддреЛрдВ рдХрд╛ рдЪрдпрди рдХрд░рддреЗ рд╣реИрдВред рдФрд░ рдЪрдпрдирд┐рдд рдлрд╝реАрд▓реНрдб рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЗ рдХреНрд░рдо рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рд╣рдо рд╕рдмрд╕реЗ рдЗрд╖реНрдЯрддрдо рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рдВрдЦреНрдпрд╛рддреНрдордХ рд╕реВрдЪрдХрд╛рдВрдХ рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬрд┐рд╕реЗ рд╣рдо рддрдм рдЦреЛрдЬ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣рддреЗ рд╣реИрдВред
рдЦреЛрдЬ рд╕реНрдерд┐рддрд┐рдпреЛрдВ, рдпрд╛ рдмрд▓реНрдХрд┐ рдмрд╣реБрд░реВрдкреА рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд╛рд░реНрдп, рд╣рдо рджреЛ рдиреЗрд╕реНрдЯреЗрдб рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рд╕рд╛рде рдЙрддреНрдкрдиреНрди рдХрд░рддреЗ рд╣реИрдВ:
  1. рдЦреЛрдЬ рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдП рд╕рднреА рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреА рдЧрдгрдирд╛ рдХрд░рдирд╛ (рдЬреИрд╕рд╛ рдХрд┐ рдкрд┐рдЫрд▓реЗ C ++ рд╕рдорд╛рдзрд╛рди рдореЗрдВ рдорд╛рдорд▓рд╛ рдерд╛)
  2. рдЦреЛрдЬ рд╢рдмреНрджреЛрдВ рдХреЗ рдХреНрд░рдо рдХреЗ рд╕рднреА рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреА рдЧрдгрдирд╛ рдХрд░рдирд╛

рдХреБрд▓ рдорд┐рд▓рд╛рдХрд░, (2^5)*5! = 32*120 = 3840 рдХрд╛ рдПрдХ рд╕рд░рдгреА рдмрдирд╛рдпрд╛ рдФрд░ рдЖрдмрд╛рдж рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ (2^5)*5! = 32*120 = 3840 (2^5)*5! = 32*120 = 3840 рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд╕рд╛рде рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди, рд▓реЗрдХрд┐рди рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдЖрдзрд╛рд░ рд╕рд╛рд░ рдкреВрд░реНрд╡рдЬ рдХреЗ рд╕рд╛рдеред
рдПрдХ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рд╕реЗ рдЕрдзрд┐рдХ рдХреЗ рд▓рд┐рдП рд░реЗрдВрдЬ рдЪреЗрдХ рд╣рдореЗрд╢рд╛ рдПрдХ рд╕рд╛рде рдЪрд▓рддреЗ рд╣реИрдВред рд╣рдо рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рд╡рд┐рдирд┐рдордп рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ рдпрд╛ рдПрдХ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рдиреНрдпреВрдирддрдо рдФрд░ рдЕрдзрд┐рдХрддрдо рдореВрд▓реНрдпреЛрдВ рдХреЗ рд╕рддреНрдпрд╛рдкрди рдХреЛ рд╕рдВрд░реЗрдЦрд┐рдд рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ рддрд╛рдХрд┐ рд╕рдВрдХрд▓рди рд╕рдордп рдореЗрдВ рджреЗрд░реА рди рд╣реЛред
рдЕрдм рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдХреЛрдб рдХреИрд╕рд╛ рджрд┐рдЦреЗрдЧрд╛ред

2. рдирд┐рд░реНрднрд░рддрд╛ рдХрдо рдХрд░рдирд╛


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдорд╛рд░реЗ рд╕рдорд╛рдзрд╛рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЯреЗрдореНрдкрд▓реЗрдЯ рд╕рдВрдХрд▓рди-рдЯрд╛рдЗрдо-рдЧреЗрдЯрд░реНрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рдХреНрд╖реЗрддреНрд░реЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдпрд╣ рдПрдХ рдЕрдЪреНрдЫрд╛ рдмреЛрдирд╕ рднреА рдЬреЛрдбрд╝ рджреЗрдЧрд╛ - рдирд┐рд░реНрднрд░рддрд╛ рдХрдо рдХрд░рдирд╛ - рдЕрдм рдХреЛрдб рдореЗрдВ рдлрд╝реАрд▓реНрдб рдХреЗ рдкреНрд░рдХрд╛рд░ рдФрд░ рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдХреЛрдИ рднреА рдкрд░рд┐рд╡рд░реНрддрди рдХреЗрд╡рд▓ T_cash_account_row. рд▓рд╛рдЗрди рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░реЗрдЧрд╛ T_cash_account_row.
рд╣рдорд╛рд░реА рдЦреЛрдЬ рдХрдХреНрд╖рд╛ рдХрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдЕрдкрд░рд┐рд╡рд░реНрддрд┐рдд рд░рд╣реЗрдЧрд╛, рдФрд░ рдПрдХ рдордирдорд╛рдирд╛ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдПрдХ рдЦреЛрдЬ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдПрдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рдЦреЛрдЬ рд╡рд░реНрдЧ рдХреЛ рддрддреНрдХрд╛рд▓ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рдпрд╣ рдЦреЗрддреЛрдВ рдХреЗ рд╕рд╛рде рдкрдВрдХреНрддрд┐ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдХреЛрдб рдХреА рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛:
 /* Row */ struct T_cash_account_row { // Fields: enum T_field_enum { amount_of_money_e, gender_e, age_e, code_e, height_e, /*<<<<<- add fields here (with index) */ last_e /*<<<<<- add included fields here (without index) */ }; static_assert(last_e > 0, "Number of indexed fields in enum of T_cash_account_row must be greater than 0!"); unsigned code:20; // 0 - 1000000 unsigned gender:1; // 0 - 1 unsigned age:7; // 0 - 100 unsigned amount_of_money:20; // 0 - 1000000 unsigned height:9; // 0 тАУ 300 // Get field value template<int field_enum> inline typename std::enable_if<field_enum == code_e, decltype(code)>::type get_field_value() const { return code; } template<int field_enum> inline typename std::enable_if<field_enum == gender_e, decltype(gender)>::type get_field_value() const { return gender; } template<int field_enum> inline typename std::enable_if<field_enum == age_e, decltype(age)>::type get_field_value() const { return age; } template<int field_enum> inline typename std::enable_if<field_enum == amount_of_money_e, decltype(amount_of_money)>::type get_field_value() const { return amount_of_money; } template<int field_enum> inline typename std::enable_if<field_enum == height_e, decltype(height)>::type get_field_value() const { return height; } template<int field_enum> inline typename std::enable_if<field_enum == last_e, bool>::type get_field_value() const { return true; } static_assert(5 == last_e, "Add/delete new field-case and correct this assert!"); }; /* ----------------------------------------------------------------------- */ 

enum T_field_enum рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ enum T_field_enum рдореЗрдВ рд╣рдореЗрд╢рд╛ 0 ( C ++ 03 7.2 рдЧрдгрди рдШреЛрд╖рдгрд╛рдкрддреНрд░ ) рд╕реЗ рд╢реБрд░реВ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рдХреНрд░рдо рдореЗрдВ рдорд╛рди рд╣реЛрддреЗ рд╣реИрдВред
std::enable_if<> #include <type_traits> рд╕реЗ #include <type_traits> рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдЖрдкрдХреЛ рдХреБрдЫ рд╡рд┐рд╢реЗрд╖ рдкреИрд░рд╛рдореАрдЯрд░ рдкреИрд░рд╛рдореАрдЯрд░ рдорд╛рдиреЛрдВ рдХреЗ рд▓рд┐рдП рдХреЗрд╡рд▓ рдлрд╝рдВрдХреНрд╢рди / рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЕрдиреНрдпрдерд╛, рдПрдХ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рддреНрд░реБрдЯрд┐ рддрд╛рддреНрдХрд╛рд▓рд┐рдХрддрд╛ рдХреЗ рджреМрд░рд╛рди рд╣реЛрддреА рд╣реИ, рдФрд░ SFINAE рдХреЗ рд╕рд┐рджреНрдзрд╛рдВрдд рдХреЗ рдЕрдиреБрд╕рд╛рд░ (рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди-рд╡рд┐рдлрд▓рддрд╛-рдПрдХ-рди-рдПрдХ рддреНрд░реБрдЯрд┐) , рдЬрдм рдПрдХ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рддреНрд░реБрдЯрд┐ рд╣реЛрддреА рд╣реИ, рдПрдХ рд╕рдВрдХрд▓рди рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ, рдФрд░ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдЙрджрд╛рд╣рд░рдг рдмрд╕ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдорд╛рдирдХ рдореЗрдВ рдЕрдзрд┐рдХ рд╡рд┐рд╡рд░рдг ( C ++ 03 14.8.2 рдЯреЗрдореНрдкрд▓реЗрдЯ рддрд░реНрдХ рдХрдЯреМрддреА )ред
рдпрд╣ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░ рдХреЗ рдЖрд╡рд╢реНрдпрдХ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рдПрдХреНрд╕реЗрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдЬреИрд╕реЗ рдХрд┐ рдЯреЗрдореНрдкрд▓реЗрдЯ рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░, рдЗрд╕ рддрд░рд╣ рд╕реЗ:
auto code = row->get_field_value<T_cash_account_row::code_e>();
рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╕рднреА 5 рдлрд╝реАрд▓реНрдб рдПрдХ рд╣реА рдкреНрд░рдХрд╛рд░ рдХреЗ рд╣реИрдВ рдФрд░ рдХреЛрдИ рднреА рдмрд┐рдирд╛ std::enable_if<> , рд▓реЗрдХрд┐рди рд╣рдо рдЖрдЧреЗ рд╕реЛрдЪрддреЗ рд╣реИрдВред рдореЗрд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдЖрдк рдХрд┐рд╕реА рднреА 5 рдлрд╝реАрд▓реНрдб рдХреЛ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЧреЗрдЯрд░реНрд╕ рд╕рдВрдХрд▓рд┐рдд рдХрд░реЗрдВрдЧреЗ рдФрд░ рдареАрдХ рдХрд╛рдо рдХрд░реЗрдВрдЧреЗред рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рдпрджрд┐ рд╣рдордиреЗ рдЙрдиреНрд╣реЗрдВ рдПрдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮрддрд╛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдмрдирд╛рдпрд╛ рд╣реИ, рддреЛ рд╣рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░реЛрдВ рддрдХ рдкрд╣реБрдВрдЪрддреЗ рд╕рдордп рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдорд┐рд▓реЗрдВрдЧреА, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдРрд╕рд╛ рдХреЛрдб рд╕рдВрдХрд▓рд┐рдд рдирд╣реАрдВ рд╣реЛрдЧрд╛:
 /* Row */ struct T_cash_account_row { // Fields: enum T_field_enum { amount_of_money_e, gender_e, age_e, code_e, height_e, /*<<<<<- add fields here (with index) */ last_e /*<<<<<- add included fields here (without index) */ }; static_assert(last_e > 0, "Number of indexed fields in enum of T_user_row must be greater than 0!"); unsigned code:20; // 0 - 1000000 unsigned gender:1; // 0 - 1 unsigned age:7; // 0 - 100 unsigned amount_of_money:20; // 0 - 1000000 int height; // 0 тАУ 300 // Get field value template<int field_enum> inline unsigned get_field_value(); template<int field_enum> inline int get_field_value(); static_assert(5 == last_e, "Add/delete new field-case and correct this assert!"); }; template<> inline unsigned T_cash_account_row::get_field_value<T_cash_account_row::code_e>() { return code; } template<> inline unsigned T_cash_account_row::get_field_value<T_cash_account_row::gender_e>() { return gender; } template<> inline unsigned T_cash_account_row::get_field_value<T_cash_account_row::age_e>() { return age; } template<> inline unsigned T_cash_account_row::get_field_value<T_cash_account_row::amount_of_money_e>() { return amount_of_money; } template<> inline int T_cash_account_row::get_field_value<T_cash_account_row::height_e>() { return height; } template<> inline unsigned T_cash_account_row::get_field_value<T_cash_account_row::last_e>() { return 1; } /* ----------------------------------------------------------------------- */ int main() { T_cash_account_row *row = new T_cash_account_row; auto code = row->get_field_value<T_cash_account_row::code_e>(); return 0; } 

рдХрдВрдкрд╛рдЗрд▓рд░ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ get_field_value<>() рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдЕрд╕реНрдкрд╖реНрдЯ рдХреЙрд▓ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХ рджреЗрдЧрд╛ред Ideone.com
рд╣рдорд╛рд░рд╛ рд╕рдВрд╕реНрдХрд░рдг рдареАрдХ рд╕рдВрдХрд▓рд┐рдд рдХрд░рддрд╛ рд╣реИ: ideone.com
рд╣рдордиреЗ рдЗрд╕реЗ рдЧреЗрдЯрд░реНрд╕ рдХреЗ рд╕рд╛рде рд╕рд╣реА рдХрд░ рд▓рд┐рдпрд╛ рд╣реИ, рдЕрдм рд╣рдо рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рд╕реЗ рдкрджреЛрдиреНрдирддрд┐ рдХреЗ рд╕рдорд╛рди рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рдЕрдирд░реЛрд▓рд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдирд┐рд░реНрдорд╛рдгрдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рдлрд╝рдВрдХреНрдЯрд░ рдХреЗ рд▓рд┐рдП (рдПрдХ рдлрд╝рдиреНрдХреНрдЯрд░ рдПрдХ рдУрд╡рд░рд▓реЛрдб рдСрдкрд░реЗрдЯрд░ рдХреЙрд▓ operator()(тАж) рд╕рд╛рде рдПрдХ рд╡рд░реНрдЧ рд╣реИ):
 // The templated functor of unrolling of the input templated functor (reusable) template<unsigned unroll_count, template<unsigned> class T> struct T_unroll_functor { T_unroll_functor<unroll_count-1, T> next_unroll; T<unroll_count-1> functor; template<typename T1, typename T2> inline bool operator()(T1 const& val1, T2 const& val2) { return next_unroll(val1, val2) && functor(val1, val2); } }; // End of unroll template<template<unsigned> class T> struct T_unroll_functor<0, T> { template<typename T1, typename T2> inline bool operator()(T1 const&, T2 const&) { return true; } }; // ------------------------------------------------------------------------- 

рдЗрд╕ рдкрджреЛрдиреНрдирддрд┐ рдХреЗ last_e , рд╣рдо last_e рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рдореВрд▓реНрдп рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдкреНрд░рддреНрдпреЗрдХ рдлрд╝реАрд▓реНрдб рдХреЗ рд▓рд┐рдП рддреБрд▓рдирд╛ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░реЗрдВрдЧреЗ рдФрд░ рдЕрдкрдиреЗ рдЯреЗрдореНрдкрд▓реЗрдЯ last_e рдорд╛рдзреНрдпрдо рд╕реЗ рдлрд╝реАрд▓реНрдб рддрдХ рдкрд╣реБрдВрдЪ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВрдЧреЗред
рдФрд░ рд╣рдо struct T_test_pred рдХреЛ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рддреИрдирд╛рдд рдХрд░реЗрдВрдЧреЗ:
 // The filters for each search variant (range_filters) template<typename T_row, unsigned index_pred> struct T_custom_filter : T_filter<T_row> { // Test predicates functor for unrolling template<unsigned field_num> struct T_test_pred { bool inline operator()(T_row *const __restrict row, T_range_filters *const __restrict range_filters) const { typedef typename T_row::T_field_enum T_field_enum; // Without fields where use_filter==0 return ( T_filter<T_row>::template T_get_use_filter<index_pred, field_num>::value || (row->template get_field_value<static_cast<T_field_enum>(field_num)>() >= range_filters->begin.template get_field_value<static_cast<T_field_enum>(field_num)>()&& row->template get_field_value<static_cast<T_field_enum>(field_num)>() <= range_filters->end.template get_field_value<static_cast<T_field_enum>(field_num)>()) ); } }; // ----------------------------------------------------------------------- // search virtual size_t search(T_row *const __restrict array_ptr, const size_t c_array_size, T_row *const __restrict result_ptr, T_range_filters *const __restrict range_filters) final { size_t result_size = 0; size_t i; // loop index T_unroll_functor<T_row::last_e, T_test_pred> test_predicate; for(i = 0; i < c_array_size; ++i) { if(test_predicate(array_ptr + i, range_filters)) result_ptr[result_size] = array_ptr[i], ++result_size; } return result_size; } }; // ------------------------------------------------------------------------- 

рдореИрдВ рдпрд╣ рднреА рдзреНрдпрд╛рди рджреЗрддрд╛ рд╣реВрдВ рдХрд┐ рдЕрдм рдХрдХреНрд╖рд╛рдУрдВ рдореЗрдВ T_filter<>, T_custom_filter<> T_optimized_search<> рдПрдХ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░ T_row , рдЬрд┐рд╕рдореЗрдВ рддрд╛рд▓рд┐рдХрд╛ рдкрдВрдХреНрддрд┐ рдкреНрд░рдХрд╛рд░ рдкрд╛рд░рд┐рдд рд╣реЛ рдЧрдпрд╛ рд╣реИ - рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, T_cash_account_row ред
рдЕрдм рдЯреЗрдмрд▓ рдлрд╝реАрд▓реНрдбреНрд╕ рдХреА рд╕рдВрдЦреНрдпрд╛, рдирд╛рдо рдФрд░ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рднреА рдкрд░рд┐рд╡рд░реНрддрди T_cash_account_row рдЕрдВрджрд░ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдХреЗрдВрджреНрд░рд┐рдд рд╣реИрдВ, рдФрд░ рд╕рдВрдкреВрд░реНрдг рдЦреЛрдЬ рдХреЛрдб рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдХрдХреНрд╖рд╛рдУрдВ рд╕реЗ рдЙрддреНрдкрдиреНрди рд╣реЛрддрд╛ рд╣реИ, рдЖрдкрдХреЛ рдмрд╕ рд╡рд╛рдВрдЫрд┐рдд рд▓рд╛рдЗрди рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ:
T_optimized_search<T_cash_account_row> optimized_search; // C++ optimized search
рдпрд╣рд╛рдБ рдкрд░рд┐рдгрд╛рдореА рдХрд╛рд░реНрдп рдХреЛрдб рдХрд╛ рд▓рд┐рдВрдХ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ: GitHub.com
рдпрд╣ рдЙрджрд╛рд╣рд░рдг рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рджрд┐рдЦрд╛рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпреЛрдВ рдХреЛрдб рдЯреАрдо-рд▓реАрдб рдФрд░ рдкреНрд░рджрд░реНрд╢рди-рд╡рд╛рд╕реНрддреБрдХрд╛рд░ рдХреЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдХреНрд╖реЗрддреНрд░реЛрдВ рдореЗрдВ рди рдХреЗрд╡рд▓ рдореЙрдбреНрдпреВрд▓ рдХреЗ рдмрд╛рд╣рд░реА рдЗрдВрдЯрд░рдлреЗрд╕ рдкрд░ рдзреНрдпрд╛рди рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдП, рдмрд▓реНрдХрд┐ рдЗрди рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рд╕рд╛рд░рд┐рдд рд╡рд╕реНрддреБрдУрдВ рдХреЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдкрд░ рднреА рдзреНрдпрд╛рди рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпреЗ рд╣реИрдВ: T_cash_account_row T_range_filters ред T_cash_account_row рдореЗрдВ рдЯреЗрдореНрдкрд▓реЗрдЯ T_cash_account_row рдорд╛рдзреНрдпрдо рд╕реЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреНрд░рдореЛрд╢рди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдореЙрдбреНрдпреВрд▓ рдХреЗ рдбреЗрд╡рд▓рдкрд░ рджреНрд╡рд╛рд░рд╛ рдФрд░ рдЕрдзрд┐рдХ рд▓рдЪреАрд▓реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдЯреАрдбреАрдбреА рдкрд░реАрдХреНрд╖рдг рдореЗрдВ рд╡рд┐рдХрд╛рд╕ рддрдХрдиреАрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХрд╛ рдЕрдзрд┐рдХ рд▓рдЪреАрд▓рд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕реЗ рдореИрдВ рдЕрдЧрд▓реЗ рд▓реЗрдЦ рдореЗрдВ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ред
рдХрдВрдкрд╛рдЗрд▓рд░ MSVC11 (MSVS2012) рдФрд░ CPU рдХреЛрд░ i5 K750 рдХреЗ рдПрдХ рдХреЛрд░ рдкрд░, рдкрд░рд┐рдгрд╛рдо рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:
рдЙрддреНрдкрдиреНрди рдкрдВрдХреНрддрд┐рдпрд╛рдБ: 10,000,000
C ++ - рдЦреЛрдЬ рд░рд╣рд╛ рд╣реИ ...
C ++ - рдЕрдиреБрдХреВрд▓рд┐рдд рдЦреЛрдЬ рдореЗрдВ 0.056000 рд╕реЗрдХрдВрдб рд▓рдЧреЗред
рдорд┐рд▓реА рдкрдВрдХреНрддрд┐рдпрд╛рдБ: 38
рд╕реА-рд╕рд░реНрдЪрд┐рдВрдЧ ...
рд╕реА-рд╕рд░реНрдЪ рдореЗрдВ 0.074000 рд╕реЗрдХрдВрдб рд▓рдЧреЗред
C ++ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ C ++ рддреЗрдЬ: 1.321429 рдмрд╛рд░
рдорд┐рд▓реА рдкрдВрдХреНрддрд┐рдпрд╛рдБ: 38

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, C ++ рдХреЛрдб C рдХреЛрдб рдХреА рддреБрд▓рдирд╛ рдореЗрдВ 1.3 рдЧреБрдирд╛ рддреЗрдЬ рд╣реИред test_predicate рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдкрд░рд┐рдгрд╛рдореА рдХреЛрдбрд╛рдВрддрд░рдХ рдХреЛрдб рдЕрднреА рднреА рдкрд┐рдЫрд▓реЗ C ++ рд╕рдВрд╕реНрдХрд░рдг, test_pradicate_enum_cpp.asm рдХреЗ рд╕рдорд╛рди рд╣реИ ред
"TortoiseDiff рд╕реЗ рд╡рд┐рд╕реНрдордпрд╛рджрд┐рдмреЛрдзрдХ рдЪрд┐рддреНрд░"
test_pradicate_enum_cpp.asm
рд▓реЗрдХрд┐рди рдЕрдм рд╣рдордиреЗ рд╕рднреА рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рдПрдХ рд╕реНрдерд╛рди рдкрд░ рдХреЗрдВрджреНрд░рд┐рдд рдХрд░ рджрд┐рдпрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдЗрд╕ рдЦреЛрдЬ рдореЙрдбреНрдпреВрд▓ рдХреЗ рдЙрдкрдпреЛрдЧ рдореЗрдВ рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛ рд╣реЛрдЧреАред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдордиреЗ рдПрдХ рдФрд░, рдФрд░ рдЕрдзрд┐рдХ рдЙрддреНрдкрд╛рджрдХ рдЕрдиреБрдХреВрд▓рди рдХреЗ рд▓рд┐рдП рдХреЛрдб рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ред

3. рддреНрд╡рд░рдг 3.5 рд╕реЗ - 5.3 рдмрд╛рд░


рдЕрдХреНрд╕рд░ C ++ рдкрд░ рдРрд╕реЗ рд▓реЗрдЦ рд╣реЛрддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рд╕рдВрдХрд▓рди-рд╕рдордп рдХреА рдЧрдгрдирд╛ рдпрд╛, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдкрд░ рдкреНрд░рдореБрдЦ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреА рдЦреЛрдЬ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд▓реЗрдЦ рджрд┐рд▓рдЪрд╕реНрдк рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЬреИрд╕рд╛ рдХрд┐ рд▓реЗрдЦрдХ рдЦреБрдж рдиреЛрдЯрд┐рд╕ рдХрд░рддреЗ рд╣реИрдВ: "рдореИрдВ рдЖрдкрдХреЛ рдмрддрд╛рдКрдВрдЧрд╛ рдХрд┐ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдмреЗрдХрд╛рд░ рдЪреАрдЬ рдХреИрд╕реЗ рдХрд░реЗрдВред"
рдореИрдВ рдЖрдкрдХреЛ рдмрддрд╛рддрд╛ рд╣реВрдВ рдХрд┐ рд╕рдВрдХрд▓рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдВрдХрд▓рди-рд╕рдордп рдХреА рдЧрдгрдирд╛ рдФрд░ рдЕрдиреБрдХреВрд▓рди рд╕реЗ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рдЦреЛрдЬ рддреНрд╡рд░рдг рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред

3.1 рд╕рд░рд▓ рдЯреЗрдореНрдкрд▓реЗрдЯ рдЧрдгрдирд╛

рдЖрдЗрдП рд╣рдо рдЬреЛ рдХреБрдЫ рднреА рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЙрд╕рдХреЗ рд╕рд░рд▓рддрдо рд╕реЗ рд╢реБрд░реВ рдХрд░реЗрдВ, рд╣рдо рд╕рдВрдХрд▓рди-рд╕рдордп рдХреА рддрдереНрдпрд╛рддреНрдордХ рдЧрдгрдирд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ:
 template <unsigned N> struct factorial : std::integral_constant<unsigned, N * factorial<N-1>::value> {}; template <> struct factorial<0> : std::integral_constant<unsigned, 1> {}; 

рд╕реНрдереИрддрд┐рдХ рд╕рд░рдгреА std::array<> рдХреЗ рдмрд░рд╛рдмрд░ рддрддреНрд╡реЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ (2^5)*5! = 3840 рд╕рд╛рде рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рднрд╛рдЬреНрдп рдЧрдгрдирд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (2^5)*5! = 3840 (2^5)*5! = 3840 ред
рдЕрд╕рддрдд рдЧрдгрд┐рдд рдФрд░ рдХреЙрдореНрдмрд┐рдиреЗрдЯрд░рд┐рдХреНрд╕ рд╕реЗ рдпрд╣ рдЬреНрдЮрд╛рдд рд╣реИ рдХрд┐ рдЕрджреНрд╡рд┐рддреАрдп рддрддреНрд╡реЛрдВ рдХреЗ рд╡рд┐рднрд┐рдиреНрди рдХреНрд░рдордкрд░рд┐рд╡рд░реНрддрди рдХреА рд╕рдВрдЦреНрдпрд╛ рдЙрдирдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рднрд╛рдЬреНрдп рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИред рдФрд░ рддрддреНрд╡реЛрдВ рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдП рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рддрддреНрд╡реЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЗ 2 рдбрд┐рдЧреНрд░реА рд╣реИред (рдмреЗрд╢рдХ, рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдмрд┐рд▓реНрдХреБрд▓ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдирд╣реАрдВ рд╣реИ рдХрд┐ рд▓рд╛рдкрддрд╛ рддрддреНрд╡реЛрдВ рдХреЛ рдХреИрд╕реЗ рдкреБрди: рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЕрддрд┐рд░рд┐рдХреНрдд рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреА рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐ рд╕рдВрдХрд▓рди рдХреЛ рдЧрддрд┐ рджреЗ рд╕рдХрддреА рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдЗрд╕ рд▓реЗрдЦ рдХреЛ рдпрдерд╛рд╕рдВрднрд╡ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред)
рдЕрдм рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдЕрдВрджрд░ рдХреНрдпрд╛ рдЕрдиреБрдХреВрд▓рди рд╣реЛрдВрдЧреЗ
struct T_custom_filter рдкрд░ struct T_custom_filter ред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдпрд╣ рдЕрдм index_order рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рднреА рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИред рдФрд░ рджреВрд╕рд░реА рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдЗрд╕рдореЗрдВ рдЦреЛрдЬреЗ рдЧрдП рдЕрдирд╡рд╛рдВрдЯреЗрдб рдлрдирдХрд╛рд░ рдХреЛ рдмрджрд▓ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
 // The filters for each search variant (range_filters) template<typename T_row, unsigned index_pred, unsigned index_order = 0> struct T_custom_filter : T_filter<T_row> { // Test predicates functor for unrolling template<unsigned field_num> struct T_test_pred { bool inline operator()(T_row *const __restrict row, T_range_filters *const __restrict range_filters) const { typedef typename T_row::T_field_enum T_field_enum; // Without fields where use_filter==0 enum { ordered_field_number = T_filter<T_row>::template T_number_field<index_order, field_num>::value }; return ( T_filter<T_row>::template T_get_use_filter<index_pred, ordered_field_number>::value || (row->template get_field_value<static_cast<T_field_enum>(ordered_field_number)>() >= range_filters->begin.template get_field_value<static_cast<T_field_enum>(ordered_field_number)>() && row->template get_field_value<static_cast<T_field_enum>(ordered_field_number)>() <= range_filters->end.template get_field_value<static_cast<T_field_enum>(ordered_field_number)>()) ); } }; // ----------------------------------------------------------------------- // search virtual size_t search(T_row *const __restrict array_ptr, const size_t c_array_size, T_row *const __restrict result_ptr, T_range_filters *const __restrict range_filters) final; }; // ------------------------------------------------------------------------- 

рдкрд╣рд▓реЗ рдХреА рддрд░рд╣, T_get_use_filter рдЯреЗрдореНрдкрд▓реЗрдЯ рдХрд┐рд╕реА рджрд┐рдП рдЧрдП index_pred рдЗрдВрдбреЗрдХреНрд╕ рдХреЗ рд▓рд┐рдП number_filter рдлрд╝реАрд▓реНрдб рджреНрд╡рд╛рд░рд╛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ (рдпрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ) рдХреЗ рд▓рд┐рдП рдПрдХ рдзреНрд╡рдЬ рджреЗрддрд╛ рд╣реИред
 // whether to use the filter for a given predicate? (strictly at compile time) template <unsigned index_pred, unsigned number_filter> struct T_get_use_filter : std::integral_constant<bool, !(index_pred & 1<<number_filter)> {}; 

T_number_field<> рдЯреЗрдореНрдкреНрд▓реЗрдЯ, index_order рдЖрдзрд╛рд░ рдкрд░ - рдлрд╝реАрд▓реНрдбреНрд╕ рдХреА рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрдВрдбреЗрдХреНрд╕ рдФрд░ field_num рдХреЗ рдлрд╝реАрд▓реНрдб рдирдВрдмрд░ рд╕реЗ, рд╣рдореЗрдВ ordered_field_number рдирдВрдмрд░ ordered_field_number рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдлрд╝реАрд▓реНрдб рдирдВрдмрд░ get_field_value<static_cast<T_field_enum>(ordered_field_number)>() ред

3.2 рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдЯреЗрдореНрдкрд▓реЗрдЯ рдЧрдгрдирд╛

рдЕрдм рдФрд░ рдХрдард┐рдиред рд╣рдо рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдХреНрд▓рд╛рд╕ T_number_field<> рдореЗрдВ рдлрд╝реАрд▓реНрдб рдСрд░реНрдбрд░ рдХреА рдЧрдгрдирд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВред рдлрд╝реАрд▓реНрдб рдСрд░реНрдбрд░ рдЗрдВрдбреЗрдХреНрд╕ index_order рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдЙрддреНрдкрдиреНрди рд╣реЛрддрд╛ рд╣реИ - рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, 5 рдлрд╝реАрд▓реНрдб рдХреЗ рд▓рд┐рдП рдЗрдВрдбреЗрдХреНрд╕ рдирд┐рдореНрди рд╕реВрддреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
index_order = field0 + 5*field1 + 5*4*field2 + 5*4*3*field3 + 5*4*3*2*field4;
рдЬрд╣рд╛рдВ рдлрд╝реАрд▓реНрдб 1 - 0 рд╕реЗ 4 рддрдХ рдлрд╝реАрд▓реНрдб рдирдВрдмрд░ (5 рдЙрдкрд▓рдмреНрдз рдореЗрдВ рд╕реЗ), рддреБрд▓рдирд╛ рдХрд░рддреЗ рд╕рдордп рдкрд╣рд▓реЗ рдЖ рд░рд╣рд╛ рд╣реИ; рдлрд╝реАрд▓реНрдб 2 - 0 рд╕реЗ 3 рддрдХ рдлрд╝реАрд▓реНрдб рд╕рдВрдЦреНрдпрд╛ (рд╢реЗрд╖ 4 рдореЗрдВ рд╕реЗ), рддреБрд▓рдирд╛ рдХрд░рддреЗ рд╕рдордп рджреВрд╕рд░рд╛ рдЖ рд░рд╣рд╛ рд╣реИ; ...; рдФрд░ рдлрд╝реАрд▓реНрдб 5 рдкрд┐рдЫрд▓реЗ рд╕реЗ рдЖрдиреЗ рд╡рд╛рд▓реЗ (0 рд╢реЗрд╖ рд╕реЗ) рдлрд╝реАрд▓реНрдб рдХреА рд╕рдВрдЦреНрдпрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╣рдореЗрд╢рд╛ 0 рд╣реЛрддрд╛ рд╣реИ, рдлрд┐рд░ рдЗрд╕реЗ рдЫреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
index_order = field0 + 5*field1 + 5*4*field2 + 5*4*3*field3;
рдпрд╛, рдЬреЛ рд╕рдорд╛рди рд╣реИ:
index_order = field0 + 5*(field1 + 4*(field2 + 3*(field3)));
рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рдпрд╣ рдЖрд╕рд╛рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдХрд┐рд╕реА рдПрдХ рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдЗрдВрдбреЗрдХреНрд╕_рдСрд░реНрдбрд░ рдХреЗ рд╡реИрд▓реНрдпреВ рдХреЛ рдкрд░рд┐рдХрд▓рд╕ рд╕рд┐рд╕реНрдЯрдо рдХреЗ рдПрдХ рд╡реИрд░рд┐рдПрдмрд▓ рдмреЗрд╕ рдХреЗ рд╕рд╛рде, рдЬрд╣рд╛рдВ field0 0 рдмреЗрд╕ 5 рдХреЗ рд╕рд╛рде рдкрд╣рд▓рд╛ рдЕрдВрдХ рд╣реИ (5 рдорд╛рди 0-4 рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ), field0 1 рдореЗрдВ рдмреЗрд╕ 4 рдХреЗ рд╕рд╛рде рджреВрд╕рд░рд╛ рдЕрдВрдХ рд╣реИ (4 рдорд╛рди рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ -3), рдФрд░ рдЗрд╕реА рддрд░рд╣ред рдЗрд╕ рдкреНрд░рдХрд╛рд░ (5!) рд╕рдВрдпреЛрдЬрди рд╣рдо рдХрд┐рд╕реА рднреА рдХреНрд╖реЗрддреНрд░ рдХреНрд░рдордкрд░рд┐рд╡рд░реНрддрди рдХреЛ рд╕рд╛рдВрдХреЗрддрд┐рдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдмреЗрд╣рддрд░ рд╕рдордЭ рдХреЗ рд▓рд┐рдП, рд╕рдВрднрд╛рд╡рдирд╛ рд╕рд┐рджреНрдзрд╛рдВрдд рдХреА рдореВрд▓ рдмрд╛рддреЗрдВ рдпрд╛ рдЕрд╕рддрдд рдЧрдгрд┐рдд рд╕реЗ рдЦреЛрдЬ рдХреЗ рд╕рд╛рде рдЦреБрдж рдХреЛ рдкрд░рд┐рдЪрд┐рдд рдХрд░рдирд╛ рдЙрдЪрд┐рдд рд╣реИред
рд╡рд┐рдЬрд╝реБрдЕрд▓реА, рдЗрд╕реЗ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ: рдХреЛрд╖реНрдардХ () рдЙрдкрд▓рдмреНрдз рд╕рдмрд╕реЗ рдХрдо рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рдореВрд▓реНрдп (рдЙрдЪреНрдЪрддрдо рдкреНрд░рд╛рдердорд┐рдХрддрд╛), рд╡рд░реНрдЧ [] - рдЙрдкрд▓рдмреНрдз рд╕реЗ рдЗрд╕рдХреА рд╕рдВрдЦреНрдпрд╛ рдФрд░ рдШреБрдВрдШрд░рд╛рд▓реЗ {} - рдХреНрд╖реЗрддреНрд░ рдХреА рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдВрдЦреНрдпрд╛ рдХреЛ рджрд░реНрд╢рд╛рддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╢реБрд░реВ рдореЗрдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирд┐рдореНрди рдкреНрд░рд╛рдердорд┐рдХрддрд╛рдУрдВ рдХреЗ рд╕рд╛рде 5 рдХреНрд╖реЗрддреНрд░ рд╣реИрдВ: 5, 3, 1, 2, 4
 рдлрд╝реАрд▓реНрдб рд╕рдВрдЦреНрдпрд╛: 0 1 2 3 4
 рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВ: 5 3 (1) 2 4 - [2] - рд╡рд░реНрддрдорд╛рди рдХреНрд╖реЗрддреНрд░ рд╕рдВрдЦреНрдпрд╛ (рдлрд╝реАрд▓реНрдб 0) {2}
 рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВ: 5 3 (2) 4 - [2] - рд╡рд░реНрддрдорд╛рди рдХреНрд╖реЗрддреНрд░ рд╕рдВрдЦреНрдпрд╛ (рдлрд╝реАрд▓реНрдб 1) {3}
 рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВ: 5 (3) 4 - [1] - рд╡рд░реНрддрдорд╛рди рдХреНрд╖реЗрддреНрд░ рд╕рдВрдЦреНрдпрд╛ (рдлрд╝реАрд▓реНрдб 2) {1}
 рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВ: 5 (4) - [1] - рд╡рд░реНрддрдорд╛рди рдХреНрд╖реЗрддреНрд░ рд╕рдВрдЦреНрдпрд╛ (рдлрд╝реАрд▓реНрдб 3) {4}
 рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВ: (5) - [0] - рд╡рд░реНрддрдорд╛рди рдХреНрд╖реЗрддреНрд░ рд╕рдВрдЦреНрдпрд╛ (рдлрд╝реАрд▓реНрдб 4) {0}

index_order = field0 + 5*(field1 + 4*(field2 + 3*(field3))); рдореЗрдВ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛: index_order = field0 + 5*(field1 + 4*(field2 + 3*(field3)));
рд╣рдореЗрдВ рд╕реВрдЪрдХрд╛рдВрдХ рдореВрд▓реНрдп рдорд┐рд▓рддрд╛ рд╣реИ: index_order = 2 + 5*(2 + 4*(1 + 3*(1))) = 92;
рдмрд╛рдж рдореЗрдВ рд╣рдо рджрд┐рдЦрд╛рдПрдВрдЧреЗ рдХрд┐ рд░рди-рдЯрд╛рдЗрдо рдлрд╝рдВрдХреНрд╢рди T_optimized_search::get_index_order(). рдореЗрдВ рдпрд╣ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ T_optimized_search::get_index_order().
рдЕрдм, рдкрджреЛрдиреНрдирддрд┐ рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рдпрд╣ рд╕реВрдЪрдХрд╛рдВрдХ рд╕рдВрдХрд▓рди рдЪрд░рдг рдореЗрдВ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЬрд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЙрд▓рдЯрд╛ рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рд╕рдВрдХрд▓рди рдХреЗ рд╕рдордп рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рд╕реАрд░рд┐рдпрд▓ рдирдВрдмрд░ рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рдПред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╡рд░реНрдЧ рдХреЛрд╖реНрдардХ рдореЗрдВ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╕реАрдЦреЗрдВ []ред рд╣рдорд╛рд░реЗ рд╡рд┐рд╢реЗрд╖ рдорд╛рдорд▓реЗ рдореЗрдВ, "рд╡рд░реНрддрдорд╛рди рдХреНрд╖реЗрддреНрд░ рд╕рдВрдЦреНрдпрд╛рдПрдБ" рдирд┐рдореНрди рдкреНрд░рдХрд╛рд░ рд╕реЗ рдкрд╛рдИ рдЬрд╛рддреА рд╣реИрдВ, рдЬреЛ рд╣рдореЗрдВ index_order = 2 + 5*(2 + 4*(1 + 3*(1))) = 92 рд▓рд┐рдП index_order = 2 + 5*(2 + 4*(1 + 3*(1))) = 92 :
 field0 = index_order% 5 = 92% 5 = 2;
 field1 = (index_order / 5)% 4 = (92/5)% 4 = 2;
 field2 = (index_order / (5 * 4))% 3 = (92/5 * 4)% 3 = 1;
 рдлрд╝реАрд▓реНрдб 3 = (рдЗрдВрдбреЗрдХреНрд╕_рдСрд░реНрдбрд░ / (5 * 4 * 3))% 2 = (92/5 * 4 * 3)% 2 = 1;
 рдлрд╝реАрд▓реНрдб 4 = 0;

рд╕рдВрдХрд▓рди-рд╕рдордп рдореЗрдВ, рдирд┐рдореНрди рдЯреЗрдореНрдкрд▓реЗрдЯ рд╡рд░реНрдЧ рдРрд╕рд╛ рдХрд░рддрд╛ рд╣реИ:
 // Get the sequence number the remaining field for the number_filter, after removal of all previous template <unsigned index_order, unsigned number_filter, unsigned index = T_row::last_e> struct T_number_remaining_field : std::integral_constant<unsigned, T_number_remaining_field<index_order / index, number_filter - 1, index - 1>::value> {}; // End of unroll template <unsigned index_order, unsigned index> struct T_number_remaining_field<index_order, 0, index> : std::integral_constant<unsigned, index_order % index> {}; // ------------------------------------------------------------------------- 

рдФрд░ рд╣рдо T_number_remaining_field<index_order, number_filter>::value рдмрд░рд╛рдмрд░ "рд╡рд░реНрддрдорд╛рди рдлрд╝реАрд▓реНрдб рдирдВрдмрд░" рдХрд╛ рдорд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕ рддрд░рд╣ рд╕реЗ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛ рддреНрд╡рд░рд┐рдд рд░реВрдк рд╕реЗ T_number_remaining_field<index_order, number_filter>::value ред
рдПрдХ рдРрд╕рд╛ рдХреНрд╖рдг рд╣реИ рдЬрд╣рд╛рдВ рдХреБрдЫ рднреНрд░рдорд┐рдд рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ: рдХреЛрдИ рд╕реЛрдЪ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ ( number_filter=0 ), рдпрд╛рдиреАред T_number_remaining_field<index_order, 0>::value рджреЛ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдЖрдВрд╢рд┐рдХ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮрддрд╛ рдХреЛ рддреБрд░рдВрдд рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
template <unsigned index_order, unsigned index> struct T_number_remaining_field<index_order, 0, index>
рдЬрд╣рд╛рдБ index_order рдХреЛ index_order рдФрд░ 0 рдХреЛ index рдореЗрдВ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдРрд╕рд╛ рд╣реИ рдирд╣реАрдВ!
рдорд╛рдирдХ ( C ++ 03 14.8.2 рдЯреЗрдореНрдкрд▓реЗрдЯ рддрд░реНрдХ рдХрдЯреМрддреА ) рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдкрд╣рд▓реЗ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рдиреЛрдВ рдХреЛ index = T_row::last_e рд▓рд┐рдП рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ index = T_row::last_e рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣рдорд╛рд░реА рддрд╛рддреНрдХрд╛рд▓рд┐рдХрддрд╛ T_number_remaining_field<index_order, 0, T_row::last_e>::value ред рдФрд░ рдлрд┐рд░ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮрддрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдкреАрд▓ рд╣реИ:
template <unsigned index_order, unsigned index> struct T_number_remaining_field<index_order, 0, index>
рдФрд░ 5 рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд╢реВрдиреНрдп рд╡рд░реНрддрдорд╛рди рдХреНрд╖реЗрддреНрд░ рд╕рдВрдЦреНрдпрд╛ ( T_row::last_e=5 ) рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рд░реВрдк рд╕реЗ index_order % 5 рдорд┐рд▓рддрд╛ рд╣реИред
рд╣рдордиреЗ рд╡рд░реНрдЧ рдХреЛрд╖реНрдардХ рдореЗрдВ рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ "рд╡рд░реНрддрдорд╛рди рдХреНрд╖реЗрддреНрд░ рд╕рдВрдЦреНрдпрд╛" рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рдзрд┐ рд▓рд╛рдЧреВ рдХреА рд╣реИред рдЕрдм рд╣рдореЗрдВ рдШреБрдВрдШрд░рд╛рд▓реЗ рдмреНрд░реЗрд╕реЗрд╕ {} рдореЗрдВ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдХреНрд╖реЗрддреНрд░ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреА рдкреНрд░рд╛рдкреНрддрд┐ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдЬреИрд╕рд╛ рдХрд┐ рд╣рдордиреЗ рдЕрдкрдиреЗ рджреГрд╢реНрдп рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рд╕реЗ рджреЗрдЦрд╛, рд╡рд░реНрдЧ рдХреЛрд╖реНрдардХ рдореЗрдВ "" рд╡рд░реНрддрдорд╛рди рдХреНрд╖реЗрддреНрд░ рд╕рдВрдЦреНрдпрд╛рдПрдБ [] рд╣рдореЗрд╢рд╛ рдХрд░реНрд▓реА рдмреНрд░реЗрд╕рд┐рдЬрд╝ рдореЗрдВ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдлрд╝реАрд▓реНрдб рд╕рдВрдЦреНрдпрд╛рдУрдВ рд╕реЗ рдореЗрд▓ рдирд╣реАрдВ рдЦрд╛рддреА {}ред рдпрджрд┐ рдЖрдк рдиреАрдЪреЗ рд╕реЗ рдКрдкрд░ рддрдХ рдмрдврд╝рддреЗ рдХреНрд░рдо рдореЗрдВ рдЧрд┐рдиреЗ рд╣реБрдП рдХрд╛рд░реНрдбреЛрдВ рдХреЗ рдПрдХ рдбреЗрдХ рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╢реБрд░реВ рдореЗрдВ рдЙрдирдХреА рд╕рдВрдЦреНрдпрд╛ рдбреЗрдХ рдореЗрдВ рдЙрдирдХреЗ рдХреНрд░рдо рдХреЗ рд╕рд╛рде рдореЗрд▓ рдЦрд╛рдПрдЧреАред рд▓реЗрдХрд┐рди рдХрд╛рд░реНрдбреЛрдВ рдХреЛ рдмреАрдЪ рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд╛рд▓рдиреЗ рд╕реЗ, рдЬреЛ рдХрд╛рд░реНрдб рдЙрдирдХреЗ рдКрдкрд░ рд╣реИрдВ рд╡реЗ рд╣рд░ рдмрд╛рд░ рдбреЗрдХ рдореЗрдВ рдпреВрдирд┐рдЯ рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдЙрдирдХреА рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд╕рд╛рдкреЗрдХреНрд╖ рдХрдо рдХрд░ рджреЗрдВрдЧреЗред
рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдЗрд╕ рддрдереНрдп рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рд╕рднреА рдХреНрд╖реЗрддреНрд░реЛрдВ рдореЗрдВ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдВрдЦреНрдпрд╛ {} рдФрд░ рдирд┐рдореНрди рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рдореВрд▓реНрдп () (рдЙрдЪреНрдЪ рдкреНрд░рд╛рдердорд┐рдХрддрд╛, рдЬреЛ рдкрд╣рд▓реЗ рд╣рдЯрд╛ рджреА рдЧрдИ рдереА), рдПрдХ "рд╡рд░реНрддрдорд╛рди рдХреНрд╖реЗрддреНрд░ рдореВрд▓реНрдп" [], рдЬрд┐рд╕рдХрд╛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдВрдЦреНрдпрд╛ рдФрд░ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рдореВрд▓реНрдп рдХрдо рд╣реЛрддрд╛ рд╣реИ рдЕрдзрд┐рдХред рдЗрд╕ рддрд░рд╣ рдХреЗ рдСрдлрд╕реЗрдЯ рдХреА рдЧрдгрдирд╛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЯреЗрдореНрдкрд▓реЗрдЯ рдХрдХреНрд╖рд╛рдУрдВ рджреНрд╡рд╛рд░рд╛ рдХреА рдЬрд╛рддреА рд╣реИ:
  // Get 1 or 0 offset if current_field (for number_filter) affect to number_field template <unsigned index_order, unsigned number_filter, unsigned number_field> struct T_offset { enum { current_field = T_number_remaining_field<index_order, number_filter>::value, value = (current_field <= number_field)?1:0 }; }; // Get offset of number_field (enum in row-type) for number_filter template <unsigned index_order, unsigned number_filter, unsigned number_field> struct T_offset_number_field { enum { offset = T_offset<index_order, number_filter-1, number_field>::value, value = T_offset_number_field<index_order, number_filter-1, number_field + offset>::value + offset }; }; // End of unroll template <unsigned index_order, unsigned number_field> struct T_offset_number_field<index_order, 0, number_field> : std::integral_constant<unsigned, 0> {}; 

рдФрд░ рдЕрдВрдд рдореЗрдВ, рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЯреЗрдореНрдкрд▓реЗрдЯ рд╡рд░реНрдЧ рдХреЗ рд╕рд╛рде рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдХреНрд╖реЗрддреНрд░ рд╕рдВрдЦреНрдпрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ:
  // (Main) Get number of field (enum in row-type) for number_filter template <unsigned index_order, unsigned number_filter> struct T_number_field { enum { remaining_field = T_number_remaining_field<index_order, number_filter>::value, value = remaining_field + T_offset_number_field<index_order, number_filter, remaining_field>::value }; }; // ------------------------------------------------------------------------- 

рд╣реЛ рдЧрдпрд╛ред

3.3 рдиреЗрд╕реНрдЯреЗрдб рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреНрд░рдЪрд╛рд░

рдЕрдм рд╣рдореЗрдВ рдлрд╝рд┐рд▓реНрдЯрд░ рдЯреЗрдореНрдкреНрд▓реЗрдЯ T_custom_filter<> рдХреЛ рдЦреЛрдЬ рдлрд╝реАрд▓реНрдбреНрд╕ рдХреА рдореМрдЬреВрджрдЧреА рдФрд░ рдЙрдирдХреЗ рдХреНрд░рдо рдореЗрдВ T_custom_filter<> рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдиреЗрд╕реНрдЯреЗрдб рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреНрд░рдЪрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ:
 template<typename T_row> class T_optimized_search { // unroll tamplates template<unsigned index_pred> struct T_unroll_find { template<unsigned index_order> struct T_unroll_order { template<typename T> T_unroll_order(T &filters) { filters[index_pred + index_order*(1<<T_row::last_e)].reset( new T_custom_filter<T_row, index_pred, index_order>() ); } }; T_unroll_constructor<factorial<T_row::last_e>::value, T_unroll_order> fill_ordered_filter; template<typename T> T_unroll_find(T &filters) : fill_ordered_filter(filters) {} }; // ------------------------------------------------------------------------- std::array<std::unique_ptr<T_filter<T_row>>, (1<<T_row::last_e)*factorial<T_row::last_e>::value> filters; T_unroll_constructor< 1<<T_row::last_e, T_unroll_find> fill_filter; public: T_optimized_search() : fill_filter(filters) {} // C++ optimized search inline size_t search(T_row *const __restrict array_ptr, const size_t c_array_size, T_row *const __restrict result_ptr, T_range_filters *const __restrict range_filters) { auto const& filter = filters[T_filter<T_row>::get_index_pred(range_filters) + T_filter<T_row>::get_index_order(range_filters)*(1<<T_row::last_e)]; return filter->search(array_ptr, c_array_size, result_ptr, range_filters); } }; // ------------------------------------------------------------------------- 

compile-time struct T_unroll_find<> , struct T_unroll_order<> .
run-time get_index_pred() тАУ , get_index_order() тАУ .
:
  // Get index of T_test_pred version for current search range static inline const unsigned get_index_pred(T_range_filters *const __restrict range_filters) { unsigned result = 0; for(size_t i = 0; i < T_row::last_e; ++i) result |= range_filters->use_filter[i]?(1<<i):0; return result; } // ------------------------------------------------------------------------- 

get_index_order() . , struct T_cash_account_row get_bitf_size() тАУ ( , switch/case, constexpr, .. compile-time, MSVC11 ):
 /* Row */ struct T_cash_account_row { ... // Get cardinality template<int field_enum> // constexpr // not supported in the MSVS2012(MVCC11) static inline const unsigned int get_bitf_size() { return (field_enum == gender_e)? 1: (field_enum == age_e)? 100: (field_enum == height_e)? 300: (field_enum == code_e)? 1000000: (field_enum == amount_of_money_e)?1000000: 0; static_assert(5 == last_e, "Add/delete new field-case and correct this assert!"); } }; 

( ):
selectivity = c_array_size * (1 + field.end тАУ field.begin) / cardinality;
, /:
  // The unrolling filling of selectivity in a compile-time template<unsigned field_num> struct T_selectivity_fill { T_selectivity_fill(std::map<unsigned, unsigned> *const __restrict ordered_filters, T_range_filters *const __restrict range_filters) { // selectivity for each field-filter const unsigned selectivity = range_filters->use_filter[field_num]? ((1 + range_filters->end.template get_field_value<field_num>() - range_filters->begin.template get_field_value<field_num>() )*c_array_size / T_row::template get_bitf_size<field_num>()) // cardinality :c_array_size; ordered_filters->insert(std::make_pair(field_num, selectivity)); } }; // Get index of T_test_pred version for current search range static inline const unsigned get_index_order( T_range_filters *const __restrict range_filters) { unsigned result = 0; std::map<unsigned, unsigned> ordered_filters; T_unroll_constructor<T_row::last_e, T_selectivity_fill> selectivity_fill(&ordered_filters, range_filters); unsigned multiplexor = 1; for(size_t i = 0; i < T_row::last_e; ++i) { unsigned cur_index = 0, min_index = 0; unsigned field_num = ordered_filters.cbegin()->first; unsigned min = c_array_size; for(auto const& it : ordered_filters) { if (it.second < min) min = it.second, field_num = it.first, min_index = cur_index; ++cur_index; } ordered_filters.erase(field_num); result += min_index*multiplexor; multiplexor *= (T_row::last_e - i); } return result; } // ------------------------------------------------------------------------- 

std::map<> , . , , std::map<> , . . , get_index_order , :
index_order = field1 + 5*(field2 + 4*(field3 + 3*(field4)));
3840 , run-time , .
test_predicate C++ тАУ , : github.com asm .
┬л TortoiseDiff┬╗
рдЫрд╡рд┐

4.


C++: GitHub.com
GCC4.7.2 тАУO3 тАУmarch=native, CPU Core i5 K750 exe- 1.3 :
Generated rows: 10000000
C++-SearchingтАж
C++-optimized search took 0.017000 seconds.
Found rows: 38
C-SearchingтАж
C-search took 0.090000 seconds.
The C++ faster than C: 5.294118 times
Found rows: 38


MSVC11(MSVS2012) /O2 /Ob2 /Oi, CPU Core i5 K750 exe- 1.42 :
рдЙрддреНрдкрдиреНрди рдкрдВрдХреНрддрд┐рдпрд╛рдБ: 10000000
C ++ - рдЦреЛрдЬ ...
C ++ - рдЕрдиреБрдХреВрд▓рд┐рдд рдЦреЛрдЬ рдореЗрдВ 0.021000 рд╕реЗрдХрдВрдб рд▓рдЧреЗред
рдорд┐рд▓реА рдкрдВрдХреНрддрд┐рдпрд╛рдВ: 38
рд╕реА-рд╕рд░реНрдЪрд┐рдВрдЧ ...
рд╕реА-рд╕рд░реНрдЪ рдореЗрдВ 0.074000 рд╕реЗрдХрдВрдб рд▓рдЧреЗред
C ++ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ C ++ рддреЗрдЬ: 3.523809 рдмрд╛рд░
рдорд┐рд▓реА рдкрдВрдХреНрддрд┐рдпрд╛рдБ: 38

рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд░рдирдЯрд╛рдЗрдо рд╕реА рдореЗрдВ 74 рд╕реЗрдВрдЯ рд╕реЗ рдЧрд┐рд░ рдЧрдпрд╛, рд╕реА ++ рдореЗрдВ 21ms рддрдХ, рдЕрд░реНрдерд╛рддреНред рдЧрддрд┐ 3.5 рдЧреБрдирд╛ рдмрдврд╝ рдЧрдИ ред рдмрд╣реБрдд рдмрдврд╝рд┐рдпрд╛ред GCC , 5.3 . - , SIMD- cache-prefetch. PGO , , 3840 .
, , C++. C++ тАУ C.
, C , . рдХреНрдпреЛрдВрдХрд┐ , C , , .
C: GitHub.com
C- diff : GitHub.com
GCC4.7.2 тАУO3 тАУmarch=native, CPU Core i5 K750 :
Generated rows: 10000000
C-optimized-SearchingтАж
C-optimized-search took 0.049000 seconds.
Found rows: 38
C-SearchingтАж
C-search took 0.086000 seconds.
The C++ faster than C: 1.755102 times
Found rows: 38

MSVC11 /O2 /Ob2 /Oi, CPU Core i5 K750 :
Generated rows: 10000000
C-optimized-SearchingтАж
C-optimized-search took 0.045000 seconds.
Found rows: 38
C-SearchingтАж
C-search took 0.074000 seconds.
The C++ faster than C: 1.644444 times
Found rows: 38

C C++ 2 тАФ 3 .
GCC C 1.8 5.3 C++, MSVC C 1.6 3.5 C++. C C++ , .

5. рдирд┐рд╖реНрдХрд░реНрд╖


, C++тАУ - 3.5-5.3 .
C, C++, .. . C тАУ C++тАУ тАУ , тАУ copy-paste.
, Java C#, .. generics , . Java C# тАУ .
, - Index Hash Join Bitmap AND, Index Organized Tables Index Only Scan. , -. 0.15 3.6 Core i5 K750, , . GPU тАУ distributed states, . web- FastCGI boost::asio. .

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


All Articles