ÕªÒª£ºÄÚÈÝÀ´Ô´ÓÚ×÷ÕßÔÚSDCC2015ÉϵÄÑݽ²£¬Ñݽ²µÄÖ÷ÌâÊǹØÓÚC++11/14µÄÐÂÌØÐÔ£¬Í¨¹ýһЩ°¸ÀýºÍ¾É±ê×¼C++98/03×öÁ˶Աȣ¬Õ¹Ê¾ÁËÐÂÌØÐÔÔÚ½â¾öÎÊÌâʱµÄÓÅÑÅÓëÇ¿´ó¡£
±¾ÎÄÄÚÈÝÀ´Ô´ÓÚÎÒÔÚSDCC2015ÉϵÄÑݽ²£¬Ñݽ²µÄÖ÷ÌâÊǹØÓÚC++11/14µÄÐÂÌØÐÔ£¬Í¨¹ýһЩ°¸ÀýºÍ¾É±ê×¼C++98/03×öÁ˶Աȣ¬Õ¹Ê¾ÁËÐÂÌØÐÔÔÚ½â¾öÎÊÌâʱµÄÓÅÑÅÓëÇ¿´ó¡£
C++11/14Ïà±ÈÒÔÍùµÄC++98/03ÔÚºÜ¶à·½Ãæ×öÁ˼ò»¯ºÍÔöÇ¿£¬ÓÈÆäÊÇÔÚ·ºÐͱà³Ì·½Ã棬ÈÃC++µÄ·ºÐͱà³ÌµÄÍþÁ¦±äµÃ¸ü¼ÓÇ¿´ó£¬±¾ÎĽ«ÓÃÈý¸ö°¸ÀýÀ´½éÉÜC++11Ïà±ÈC++98/03ÈçºÎÒÔÒ»ÖÖ¸üÁé»î¡¢¸ü¼ò½àºÍ¸ü·º»¯µÄ·½Ê½È¥½â¾öÎÊÌâ¡£
¼ì²é³ÉÔ±º¯ÊýÊÇ·ñ´æÔÚ
ÓÐÕâÑùÒ»¸ö³¡¾°£¬ÐèÒªÅжÏij¸öÀàÐÍÊÇ·ñ´æÔÚ³ÉÔ±º¯Êýfoo£¬Èç¹û´æÔھ͵÷ÓÃÕâ¸ö³ÉÔ±º¯Êý£¬·ñÔò¾ÍÖ´ÐÐĬÈϵĺ¯Êý£¬ÏÂÃæÊÇα´úÂë¡£
template<typename T> void foo(const T& t) { if (t has foo) t.foo(); else default(); } |
ÔÚÓз´ÉäµÄÓïÑÔÀÈçc#ºÍjavaÀÕâÊǺÜÈÝÒ׵ģ¬È»¶øC++ûÓз´É䣬C++98/03ÖÐҪʵÏÖÕâ¸öÂß¼£¬ÐèÒª½èÖúSFINAE£¨substitution is not an error£©ÌØÐÔ¡£ÊµÏÖÕâ¸öÂß¼·ÖΪÁ½²½£¬µÚÒ»²½ÔÚ±àÒëÆÚ¼ì²é³ÉÔ±º¯ÊýfooÊÇ·ñ´æÔÚ£¬µÚ¶þ²½¸ù¾ÝµÚÒ»²½µÄ¼ì²é½á¹ûÀ´Ñ¡Ôñ·ÖÖ§¡£C++98/03ÀïµÄ×ö·¨ÊÇÕâÑùµÄ¡£
template<typename T> struct has_member_foo { template<typename U, void(U::*)()> struct SFINAE {}; template<typename U> static char check(SFINAE<U, &U::foo>*); template<typename U> static int check(...); static const bool value = sizeof(check<T>(0)) == sizeof(char); }; |
Ôªº¯Êýhas_member_fooÖж¨ÒåÁËÒ»¸ö¸¨Öú½á¹¹ÌåSFINAEºÍÖØÔØº¯Êýcheck£¬¸¨Öú½á¹¹ÌåÔÚÄ£°åʵÀý»¯µÄʱºò¿ÉÒÔÈ·¶¨ÀàÐÍUÊÇ·ñ´æÔÚfoohº¯Êý£»checkÖØÔØº¯ÊýÀûÓÃÁËSFINAE£¨substitution is not an error£©ÌØÐÔ£¬±àÒëÆ÷»á¸ù¾ÝÖØÔØ¾öÒéÑ¡Ôñ×îºÏÊʵĺ¯Êý£¬µ±¸¨Öú½á¹¹ÌåʵÀý»¯³É¹¦Ê±£¬µÚÒ»¸öcheckº¯ÊýµÄÓÅÏȼ¶¸ü¸ß£¬Èç¹ûʵÀý»¯Ê§°ÜÔò»áÑ¡ÔñÓÅÏȼ¶×îµÍµÄcheck(...)º¯Êý£¬ÕâÁ½¸öÖØÔØº¯ÊýµÄ·µ»ØÀàÐͲ»Ïàͬ£¬ÎÒÃǸù¾Ýº¯Êý·µ»ØÀàÐ͵Äsize¾Í¿ÉÖªµÀÀàÀïÊÇ·ñ´æÔÚ³ÉÔ±º¯ÊýfooÁË¡£ÏÂÃæÊDzâÊÔ´úÂë¡£
struct MyStruct { void foo() { } }; static_assert(has_member_foo<MyStruct>::value, "true"); //¶ÏÑÔͨ¹ý static_assert(has_member_foo<int>::value, "false"); //¶ÏÑÔ´íÎó |
C++11µÄʵÏÖ·½Ê½ÊÇÕâÑùµÄ¡£
template<typename T> struct has_member_foo11 { private: template<typename U> static auto check(int) -> decltype(std::declval<U>().foo(), std::true_type()); template<typename U> static std::false_type check(...); public: enum { value = std::is_same<decltype(check<T>(0)), std::true_type>::value }; }; |
C++11µÄʵÏÖ²»ÐèÒª¸¨Öú½á¹¹Ì壬Óõ½Á˼¸¸öC++11µÄÐÂÌØÐÔ£ºauot¡¢decltype¡¢·µ»ØÀàÐͺóÖá¢declvalºÍtrype_traits¡£¾ßÌåµÄʵÏÖÔÀíÊÇÕâÑùµÄ£ºÍ¨¹ý·µ»ØÀàÐͺóÖÃÀ´Íƶϱí´ïʽµÄÀàÐÍ£¬ÍƶϵĹý³ÌÖÐÀûÓÃdeclval£¬Ëü¿ÉÒÔ»ñÈ¡ÀàÐ͵ÄÓÒÖµÒýÓã¬ÒÔ±ãÀ´µ÷ÓóÉÔ±º¯Êý£¬Õâ¸ö¹ý³ÌÊÇÔÚ±àÒëÆÚÍê³ÉµÄ¡£Èç¹ûͨ¹ýdeclvalµ÷ÓóÉÔ±º¯Êý³É¹¦ÁË£¬Ôò»á¼ÌÐøÍÆ¶Ï¶ººÅ±í´ïʽµÄÀàÐÍ£¬×îÖÕÍÆ¶ÏµÄº¯Êý·µ»ØÀàÐÍΪstd::true_type£»Èç¹ûͨ¹ýdeclvalµ÷ÓóÉÔ±º¯Êýʧ°ÜÁËÔòÍÆ¶Ïʧ°Ü£¬±àÒëÆ÷»áÑ¡ÔñÓÅÏȼ¶×îµÍµÄcheck(...)º¯Êý£¬ËüµÄ·µ»ØÀàÐÍΪstd::false_type¡£ÎÒÃÇ×îºó¸ù¾Ý·µ»ØÀàÐͼȿÉÖªµÀÀàÐÍÊÇ·ñ´æÔÚfooº¯Êý¡£
ËäÈ»C++98/03ºÍC++11Á½ÖÖд·¨¶¼¿ÉÒÔÍÆ¶Ï³öÊÇ·ñ´æÔÚ³ÉÔ±º¯Êýfoo£¬µ«Êǵ±Çé¿öÉÔ΢·¢ÉúÒ»µã±ä»¯Ê±£¬¾Í»á³öÏÖÒ»¸öÎÊÌ⣬±ÈÈçÏÂÃæµÄ´úÂë¡£
struct MyStruct { int foo() { } }; static_assert(has_member_foo<MyStruct>::value, "false"); //¶ÏÑÔ´íÎó static_assert(has_member_foo11<MyStruct>::value, "true"); |
µ±ÎÒÃǰÑfooµÄ·µ»ØÀàÐÍÐÞ¸ÄΪintʱ£¬C++98/03°æ±¾µÄÔªº¯Êý¾ÍÍÆ¶Ï²»³öÀ´£¬ÔÒòÊÇÒòΪÎÒÃǶ¨Ò帨Öú½á¹¹ÌåʱÏÞ¶¨Á˺¯ÊýÇ©Ãûtemplate struct SFINAE {}£¬Õâ¸öÖ»ÄÜʵÀý»¯void()ÀàÐ͵ĺ¯Êý£¬¶ÔÓÚ·µ»ØÀàÐÍΪintµÄº¯Êý¾ÍÎÞÄÜΪÁ¦ÁË¡£µ«ÊǶÔÓÚC++11°æ±¾µÄÔªº¯ÊýÀ´ËµÃ»ÓÐÎÊÌ⣬ÒòΪC++11ûÓÐÏÞ¶¨·µ»ØÀàÐÍ£¬declval²»¹ØÐĺ¯Êý·µ»ØÀàÐÍ£¬ËüÖ»ÊÇÔÚ±àÒëÆÚµ÷ÓÃÁ˳ÉÔ±º¯Êý¡£´ÓÕâÀï¿ÉÒÔ¿´µ½C++11µÄʵÏÖ·½Ê½¸üÁé»î£¬µ«ÊÇÕâ¸öʵÏÖ»¹²»¹»Í¨Óã¬ÒòΪËüÖ»ÄÜÍÆ¶Ï²»º¬²ÎÊýµÄfoo£¬Èç¹û´æÔÚº¬²ÎµÄÖØÔØº¯Êýfoo£¬¸ÃÈçºÎ´¦ÀíÄØ£¿Õâ¸öÎÊÌâ¶ÔÓÚC++98/03À´Ëµ¼¸ºõÊÇÎÞ·¨½â¾öµÄÒ»¸öÎÊÌ⣬µ«¶ÔÓÚC++11À´ËµÊǺÜÇáËɵÄÒ»¼þÊÂÇ飬ͨ¹ýC++11µÄÐÂÌØÐÔ--¿É±äÄ£°æ²ÎÊý¼´¿É½â¾ö¡£ÏÂÃæÊÇͨÓð汾µÄʵÏÖ¡£
template<typename T, typename... Args> struct has_member_foo11 { private: template<typename U> static auto check(int) -> decltype(std::declval<U>().foo(std::declval<Args>()...), std::true_type()); template<typename U> static std::false_type check(...); public: enum { value = std::is_same<decltype(check<T>(0)), std::true_type>::value }; }; |
²âÊÔ´úÂ룺
struct MyStruct { string foo() { return ""; } int foo(int i) { return i; } }; static_assert(has_member_foo<MyStruct>::value, "true"); static_assert(has_member_foo<MyStruct, int>::value, "true"); |
ËäÈ»ÎÒÃǽèÖú¿É±äÄ£°æ²ÎÊý½â¾öÁËÖØÔØº¯ÊýµÄÎÊÌ⣬µ«»¹ÓÐÒ»¸ö²»×ãÖ®´¦£¬ËüÖ»Äܼì²éº¯ÊýÃûΪfooµÄÀ࣬Èç¹ûÐèÒª¼ì²éÆäËüº¯ÊýÃûµÄÀ࣬ÔòÐèÒªÔÙ¶¨ÒåÒ»¸ö¼¸ºõÏàͬµÄÀ࣬ÕâÑù×ö·±Ëö¶øµÍЧ¡£Öظ´¶¨ÒåµÄÎÊÌâÎÒÃÇ¿ÉÒÔ½èÖúºêÀ´½â¾ö¡£ÏÂÃæÊÇʵÏÖ´úÂë¡£
#define HAS_MEMBER(member)\ template<typename T, typename... Args>struct has_member_##member\ {\ private:\ template<typename U> static auto Check(int) -> decltype(std::declval<U>().member(std::declval<Args>()...), std::true_type());\ template<typename U> static std::false_type Check(...);\ public:\ enum{value = std::is_same<decltype(Check<T>(0)), std::true_type>::value};\ }; |
ÕâÑùÿ´ÎÐèÒª¼ì²é²»Í¬º¯ÊýÃûµÄʱºòÖ»ÐèÒª¶¨ÒåÒ»¸ö¼òµ¥µÄºê¼´¿É£¬±ÈÈçÎÒÃÇÐèÒª¼ì²éfooºÍfuncº¯Êýʱ£¬¿ÉÒÔÕâÑù¶¨Òå¡£
HAS_MEMBER(foo) HAS_MEMBER(func) |
²âÊÔ´úÂ룺
struct MyStruct { string foo() { return ""; } int func(int i) { return i; } }; static_assert(has_member_foo<MyStruct>::value, "true"); static_assert(has_member_func<MyStruct, int>::value, "true"); |
½èÖúC++11µÄÐÂÌØÐÔÎÒÃÇÍêÃÀµØ½â¾öÁ˼ì²é³ÉÔ±º¯ÊýÊÇ·ñ´æÔÚµÄÎÊÌ⣬ÔÙ»ØÍ·À´¿´ÎÄÕ¿ªÊ¼Ìá³öµÄÎÊÌ⣬ÎÒÃÇʵÏÖÁ˽â¾öÎÊÌâµÄµÚÒ»²½£¬µÚ¶þ²½ÐèÒªÔÚµÚÒ»²½ÅжϵĻù´¡ÉÏÑ¡Ôñ·ÖÖ§¡£Í¬Ñù½èÖúC++11ÖеÄtype_traitsÀ´ÊµÏÖ±àÒëÆÚÑ¡Ôñ·ÖÖ§£¬¾ßÌåÊÇͨ¹ýenable_ifÀ´ÊµÏֵġ£
template<typename T> typename std::enable_if<has_member_foo11<T, int>::value>::type testfun(T t) { cout << "has foo" << endl; } template<typename T> typename std::enable_if<!has_member_foo11<T, int>::value>::type testfun(T t) { cout << "has no foo" << endl; } |
×îÖÕÎÒÃǽèÖúC++11ÍêÃÀµØ½â¾öÁ˱àÒëÆÚ¼ì²é³ÉÔ±º¯ÊýÊÇ·ñ´æÔÚ²¢ÇÒÔÚ±àÒëÆÚÑ¡Ôñ·ÖÖ§µÄÎÊÌ⣬ʵÏÖ·½Ê½Ïà±ÈC++98/03¸ü¼Ó¼ò½à¡¢Áé»îºÍͨÓá£
º¯Êý»º´æ
ΪÁËÓÅ»¯³ÌÐòÐÔÄÜÎÒÃǾ³£Ê¹Óûº´æ£¬±ÈÈçij¸öº¯Êý·Ç³£ºÄʱ£¬Æµ·±µ÷ÓõÄʱºòÐÔÄÜ»áºÜµÍ£¬ÕâʱÎÒÃǾͿÉÒÔͨ¹ý»º´æÀ´Ìá¸ßÐÔÄÜ¡£ÏÈ¿´¿´ÏÂÃæµÄ´úÂë¡£
size_t fibonacci(size_t n) { return (n < 2) ? n : fibonacci(n - 1) + fibonacci(n - 2); } void test() { Timer t; size_t n = fibonacci(45); cout << n << " " << t.elapsed() << endl; } |
Õâ¸ö´úÂëÔÚÆÕͨ˫ºË±Ê¼Ç±¾ÉϺÄʱ8Ãë¶à£¬Õâ¸öº¯Êý¸ÕºÃ¿ÉÒÔͨ¹ý»º´æÀ´ÓÅ»¯¡£
size_t fibonacci(size_t n) { return (n < 2) ? n : sugar(fibonacci2)(n - 1) + sugar(fibonacci2)(n - 2); } |
ÓÅ»¯Ö®ºóµÄfibonacciÏà±È֮ǰµÄfibonacci2½ö½öÊǶàÁËÒ»¸ösugar£¬È»¶øÐÔÄÜÈ´¿ÉÒÔÌá¸ßÊýÊ®±¶£¬ÒòΪsugarÄÚ²¿×öÁË»º´æ£¬ÏÂÃæÀ´¿´¿´sugarµÄ¾ßÌåʵÏÖ¡£
template <typename R, typename... Args> std::function<R(Args...)> sugar(R(*func)(Args...), bool needClear = false) { using function_type = std::function<R(Args...)>; static std::unordered_map<decltype(func), function_type> functor_map; if (needClear) return functor_map[func] = cache(func); if (functor_map.find(func) == functor_map.end()) functor_map[func] = cache(func); return functor_map[func]; } |
sugarº¯ÊýÄÚ²¿ÓÐÒ»¸ömap£¨×¢Ò⣬ÕâÀïÓõľ²Ì¬¾Ö²¿±äÁ¿£¬C++11Öеľ²Ì¬¾Ö²¿±äÁ¿ÊÇḬ̈߳²È«µÄ£©£¬ÓÃÀ´±£´æ±»»º´æº¯ÊýµÄº¯ÊýÖ¸ÕëºÍÒ»¸östd::function£¬std::functionÓÖÊÇ´Ócacheº¯Êý·µ»Ø³öÀ´µÄ£¬½ÓÏÂÀ´¿´¿´cacheµÄʵÏÖ¡£
template <typename R, typename... Args> std::function<R(Args...)> cache(R(*func) (Args...)) { auto result_map = std::make_shared<std::map<std::tuple<Args...>, R>>(); return ([=](Args... args){ std::tuple<Args...> t(args...); if (result_map->find(t) == result_map->end()) (*result_map)[t] = func(args...); return (*result_map)[t]; }); } |
cacheÄÚ²¿ÓÐÒ»¸ömap£¬Ëü±£´æÁ˱»»º´æº¯Êýµ÷ÓÃʱµÄÈë²ÎºÍº¯ÊýµÄÖ´Ðнá¹û¡£cacheº¯Êý»¹¶¨ÒåÁËÒ»¸ölambda±í´ïʽ£¬ÓÃÓÚÑÓ³ÙÖ´ÐУ¬ÔÚÍâÃæµ÷ÓÃfunctionʱ²ÅÖ´ÐС£LambdaÄÚ²¿µÄÂß¼ºÜ¼òµ¥¾ÍÊDZ£´æµ÷ÓÃʱµÄ²ÎÊýºÍÖ´Ðнá¹û£¬µ±Ï´ε÷ÓÃʱ»áÏȼì²éµ÷ÓõIJÎÊýÊÇ·ñÒѾ´æÔÚ£¬Èç¹ûÒѾ´æÔÚÔò´Ó»º´æmapÖзµ»Ø£¬Èç¹û²»´æÔڲŵ÷Óñ»»º´æµÄº¯Êý£¬Í¬Ê±±£´æÐµĵ÷ÓòÎÊýºÍµ÷Óýá¹û¡£Í¼1ÊÇfibonacciº¯Êý»º´æµÄ¹ý³Ì¡£

ͼ1 fibonacciº¯Êý»º´æµÄ¹ý³Ì
C++11ʵÏÖµÄÕâ¸öº¯Êý»º´æÏà±È´«Í³µÄ»º´æ·½·¨À´ËµÓÐÏÂÃæ¼¸¸öÓŵ㣺
1£®Ïà±È´«Í³µÄ»º´æÊµÏÖ·½Ê½£¬Ëü¸üͨÓ㬿ÉÒÔÊÊÓ¦Èκκ¯Êý£¬ÎÞÐèΪÿһ¸ö±»»º´æº¯Êý¶¨ÒåרÃŵĻº´æ¶ÔÏó¡£
2£®¸ü¼ò½à£¬Ö»ÐèÒªÒ»¸ösugar¼È¿ÉÒÔʵÏÖ»º´æ¡£
ʵÏÖÒ»¸öhttp router
http routerÊÇweb·þÎñÆ÷µÄÒ»¸öºËÐÄÄ£¿é£¬Ëü»á½âÎöurl£¬È»ºó·Óɵ½ÕýÈ·µÄhandlerÉÏ£¬ÏÂÃæÊÇcinatra¿ò¼Ü£¨Ò»¸öÏÖ´úC++дµÄweb framework£©µÄÓ÷¨¡£
Cinatra app; app.route("/hello", [](Request& req , Response& res) { res.end("Hello "); }); app.route("/hello/:name/:age", [](Request& req, Response& res, const std::string& a, int b) { res.end("Name: " + a + ", Age: " + boost::lexical_cast<std::string>(b)); }); |
µ±Óû§ÔÚä¯ÀÀÆ÷ÖÐÊäÈëhttp://127.0.0.1/helloʱ£¬»á·Óɵ½µÚÒ»¸öhandler£¬µ±Óû§ÊäÈëhttp://127.0.0.1/hello/test/20ʱ£¬»á·Óɵ½µÚ¶þ¸öhandler¡£CinatraÖ§³Ö¶àÖÖ·½Ê½µÄÇëÇ󣬱ÈÈçhttp://127.0.0.1/hello/test/20ÕâÖÖÇëÇó£¬ËüÊǷDZê×¼µÄ£¬µ«Ëü¿ÉÒÔ·½±ãÓû§Ê¹Óã¬Óû§²»±ØÍ¨¹ýget²ÎÊýµÄ·½Ê½È¥ÇëÇóÁË£¬Ö±½Ó½«²ÎÊý·Åµ½ºóÃæ£¬Ê¹ÓÃÆðÀ´ºÜ·½±ã¡£µ«ÊÇÕâÖÖ·½Ê½µÄʵÏÖÈ´ºÜÀ§ÄÑ£¬ÊµÏÖÕâÖÖ·½Ê½µÄ±¾ÖÊÊÇ×Ö·û´®µ½º¯Êýµ÷ÓõÄÓ³É䣬Èçͼ2Ëùʾ¡£

ͼ2
Èç¹ûÏëͨ¹ýC++98/03À´ÊµÏÖ¼¸ºõÊDz»¿ÉÄÜÍê³ÉµÄÈÎÎñ£¬µ«¶ÔÓÚC++11À´ËµÈ´²»ÊÇÄÑÌâ¡£
C++11µÄʵÏÖ˼·ÈçÏ£º
1. ½âÎöurl½«²ÎÊý·Ö¸î£¬·Ö¸îÖ®ºóµÄ×Ö·û´®·Åµ½ÁбíÖÐ{"hello", "test", "2"}£»
2. ½«ÁбíÖеIJÎÊýת»»ÎªfunctionµÄʵ²Î£»
2-1. ½«ÁбíÖеIJÎÊý·Ö±ðת»»ÎªfunctionµÄʵ²Î¡£
2-2. ½«×ª»»ºóµÄʵ²ÎÒ»¸öÒ»¸ö±£´æµ½¡°ÈÝÆ÷¡±--tupleÖС£
2-3. ½«tupleת»»Îªº¯Êýʵ²Î¡£
3. handlerµ÷Óá£
ʵÏֵĹؼüÔÚÓÚÈçºÎ½«·Ö¸îµÄ×Ö·û´®Ò»¸öÒ»¸öת»»ÎªhandlerµÄʵ²Î£¬×ª»»Ö®ºóÓÖÈçºÎʵÏÖµ÷Ó᣽«×Ö·û´®×ª»»ÎªhandlerµÄʵ²Î½èÖúÁËfunction_traits£¬Ëü¿ÉÒÔ»ñÈ¡º¯Êýÿһ¸ö²ÎÊýµÄÀàÐÍ£¬ÖªµÀÕâ¸öÀàÐÍÖ®ºóÎÒÃǾͿÉÒÔ½«×Ö·û´®×ª»»Îª¶ÔÓ¦ÀàÐ͵ÄÖµÁË£¬¼´º¯Êýʵ²Î¡£×ª»»Ö®ºó»¹Òª¿¼ÂDZ£´æµÄÎÊÌ⣬ÒòΪº¯Êýʵ²ÎµÄÀàÐÍÊDz»Í¬µÄ£¬ÆÕͨµÄÈÝÆ÷ÊÇÎÞ·¨±£´æ²»Í¬ÀàÐ͵ÄÊý¾ÝµÄ£¬ÕâÀï½èÖútupleÀ´±£´æÀàÐͲ»Í¬µÄʵ²Î¡£±£´æÊµ²ÎÖ®ºó»¹ÐèÒªÍê³Éº¯Êýµ÷Óã¬ÕâÀïÐèҪͨ¹ý¿É±äÄ£°æ²ÎÊýºÍtupleÏ໥ת»»À´ÊµÏÖº¯Êýµ÷Óá£ÏÂÃæÀ´¿´¿´ÊµÏֵĹؼü¼¼Êõ¡£
¡¾×Ö·û´®×ª»»Îª¶ÔÓ¦µÄº¯Êýʵ²Î¡¿
ͨ¹ýfunction_traitsÀ´»ñÈ¡º¯Êý²ÎÊý¸öÊýºÍÿ¸ö²ÎÊýµÄÀàÐÍ£¬»ñȡ֮ºó¾Í¿ÉÒÔµ÷ÓÃboost.lexicastÀ´½«×Ö·û´®×ª»»Îª¶ÔÓ¦µÄ²ÎÊýÖµÁË£¬½ÓÏÂÀ´½«×ª»»Ö®ºóµÄ²ÎÊý·Åµ½tupleÖУ¬ÒÔ±¸ÓÃÓÚÔÚÏÂÒ»²½µÄº¯Êýµ÷Óá£ÏÂÃæÊÇʵÏֵĹؼü´úÂ룬ÍêÕûµÄ´úÂë¶ÁÕß¿ÉÒԲο¼ÎÒgithubÉϵĴúÂ룺https://github.com/kxjhcs/cosmos/blob/master/router.hpp¡£
template<typename Function, size_t N = 0, size_t M = function_traits<Function>::arity> struct invoker { template<typename Args> static inline void apply(const Function& func, token_parser & parser, Args const & args) { typedef typename function_traits<Function>::template args<N>::type arg_type; router::invoker<Function, N + 1, M>::apply(func, parser, std::tuple_cat(args, std::make_tuple(parser.get<arg_type>()))); } }; template<typename Function, size_t M> struct invoker<Function, M, M> { template<typename Args> static inline void apply(const Function& func, token_parser &, Args const & args) { //²ÎÊýÁбíÒѾ׼±¸ºÃ£¬¿ÉÒÔµ÷ÓÃfunctionÁË call(func, args); } }; |
¡¾ÊµÏÖº¯Êýµ÷Óá¿
ÔÚÇ°ÃæÎÒÃÇÒѾ½«×Ö·û´®×ª»»ÎªÊµ²Î²¢±£´æµ½tupleÖÐÁË£¬½ÓÏÂÀ´ÎÒÃÇÐèÒª½«tupleת»»Îªº¯Êýʵ²ÎÁÐ±í£¬ÕâÐèҪͨ¹ý½«tupleת»»Îª¿É±äÄ£°æ²ÎÊý£¬ÏÂÃæÊÇʵÏֵĹؼü´úÂë¡£
template<typename F, int ... Indexes, typename ... Args> static void call_helper(F f, IndexTuple<Indexes...>, const std::tuple<Args...>& tup) { f(std::get<Indexes>(tup)...); } template<typename F, typename ... Args> static void call(F f, const std::tuple<Args...>& tp) { call_helper(f, typename MakeIndexes<sizeof... (Args)>::type(), tp); } |
ÆäÖУ¬MakeIndexesÉú³ÉÁËÒ»¸öÕûÐÎÐòÁУ¬Í¨¹ýÕâ¸öÕûÐÎÐòÁоͿÉÒÔ½«tupleת»»Îª¿É±äÄ£°å²ÎÊý²¢Íê³Éº¯Êýµ÷ÓÃÁË¡£MakeIndexesµÄ¾ßÌåʵÏÖ¶ÁÕß¿ÉÒԲο¼githubÉϵĴúÂ룬ÆäʵÔÚC++14µÄutility¿âÖÐÒѾÌṩÁËstd::index_sequenceºÍstd::make_index_sequence£¬´úÂë»á¸ü¼Ó¼ò½à¡£
C++11ʵÏÖµÄhttp router²»½ö½ö¿ÉÒÔÓÃÓÚhttp·þÎñÆ÷¶ËµÄ·ÓÉ£¬»¹¿ÉÒÔʵÏÖrpcºÍmvc¿ò¼ÜµÄ·ÓÉ£¬ËùÒÔÓÃC++11È¥×öweb¿ª·¢Ò²ÊÇÍêÈ«¿ÉÒԵġ£
×ܽá
±¾ÎÄÏÈͨ¹ý½éÉܼì²é³ÉÔ±º¯ÊýÊÇ·ñ´æÔÚ£¬±È½ÏÁËC++98/03ºÍC++11µÄʵÏÖ²îÒ죬C++11µÄʵÏÖÎÞÒɸü¼Ó¼ò½àºÍͨÓã¬ÍêÃÀµØ½â¾öÁËÎÊÌ⣬ÌåÏÖÁËÏÖ´úC++½â¾öÎÊÌâµÄ¼«ÖÂÖ®ÃÀ¡£½Ó׎éÉÜÁËÈçºÎʵÏÖÒ»¸öͨÓõĺ¯Êý»º´æ£¬½ö½öÒ»¸ö·º»¯µÄº¯Êý¼È¿ÉÒÔʵÏÖ»º´æÈÎÒ⺯Êý£¬ÌåÏÖÁËÏÖ´úC++µÄ¼ò½àÖ®ÃÀºÍ·º»¯Ö®ÃÀ¡£×îºóչʾÁËÏÖ´úC++ÔÚ×öweb¿ª·¢µÄʱºòÈçºÎʵÏÖÁé»îµÄ·ÓÉ£¬Íê³ÉÁË֮ǰC++98/03¼¸ºõ²»¿ÉÄÜÍê³ÉµÄÈÎÎñ£¬ÌåÏÖÁËÏÖ´úC++µÄÍþÁ¦£¬²»½ö½öÊÇÉú²úÁ¦µÄ¾Þ´óÌáÉý¡£
ÏÖ´úC++ÈÔÈ»ÔÚ·¢Õ¹ÍêÉÆµ±ÖУ¬³ýÁ˽üÄê³öÏÖµÄC++11/14£¬Î´À´µÄC++17/20±ê×¼ÕýÔÚ¹æ»®ÖÆ¶¨µ±ÖС£C++17½«ÒýÈë¸ü¶àµØ¼¤¶¯ÈËÐĵÄÌØÐÔ£¬Óв¢ÐС¢²¢·¢¡¢ÍøÂç¿â¡¢Ð³Ì¡¢modulesºÍconceptsµÈµÈ£¬Õ⽫ÊÇC++·¢Õ¹Ê·ÉϵÄÒ»×ùÀï³Ì±®¡£
ÏÖ´úC++ÏÈÌìµÄÐÔÄÜÓÅÊÆÓëºóÌìµÄЧÂÊ£¨ÏÖ´ú¡¢¿ìËÙ¿ª·¢£©ÓÅÊÆ£¬³ýÁË´«Í³µÄ·þÎñ¶Ë¡¢ÓÎÏ·¡¢°²È«¡¢Ç¶ÈëʽºÍÒôÊÓÆµµÈÁìÓòÍ⣬ÓÃÀ´×öÒÆ¶¯»¥ÁªÍø¡¢ÔÆÆ½Ì¨ºÍ´óÊý¾Ý·ÖÎöÕýµ±Æäʱ¡£
|