C++åå¿è ä¼ã§è©±é¡ã«ãªã£ãClangã®ç¸äºå帰ãã°ã«ã¤ãã¦
ä¸ï¼å¥³åã§ãã
æèä¼åº§.tech#8ãC++åå¿è ä¼ãã¨ããåå¼·ä¼ãå æ¥ãããèªç§°åå¿è ãã¯ã½ã¶ã³ã«ãããã¾ãã¾ãªçºè¡¨ããããªããããèªåã¯åå ã§ããªãã£ãã®ã§ãããã¤ãã®çºè¡¨ããã³çã§è¦è´ããã
ãã®ä¸ã«ã@wx257osn2 æ°ã«ãã constexpr ã©ã ãã©ã¤ãã©ãªãå®è£ ããã¨ããçºè¡¨ããã£ããå®è£ ã«ããã£ã¦ã¯ Clang ã®ãã°ã«å¯¾å¦ããã¯ã¼ã¯ã¢ã©ã¦ã³ããæ¸ãã®ã«è¦å´ããã¨ããããããããªããClang ã¯å ¨ä½çãªè¦æ ¼æºæ 度ã§ã¯ãããã GCC 以ä¸ã¨ãã£ã¦ããããconstexpr é¢ä¿ã§ã¯ãã¾ã ã«è´å½çãªãã°ãæ®ãã¦ããããããã©ã®ãããªãã°ãªã®ãå¿çã§é½é½¬ããã£ããããªã®ã§ãèããã®è£è¶³ãããã«è¨ãã¦ããã
Clang ã® constexpr é¢ä¿ã®è´å½çãªãã°ã¨ã¯ãç¸äºå帰ã«ããããã°ã§ãããç¸äºå帰ãã constexpr é¢æ°ãã³ãã¬ã¼ããå®ä½åããã¨ããã³ãã¬ã¼ãã¤ã³ã¹ã¿ã³ã¹åãç¡éå帰ãã¦ã³ã³ãã¤ã«ã¨ã©ã¼ã«ãªããå ·ä½çã«ã¯ä»¥ä¸ã®ãããªã³ã¼ããã¨ã©ã¼ã¨ãªãã
template<typename T> constexpr T f(T const&); template<typename T> constexpr T g(T const&); template<typename T> constexpr T f(T const& val) { return g(val); } template<typename T> constexpr T g(T const& val) { return val >= 10 ? val : f(val + 1); } int main() { constexpr auto x = f(0); // [clang version 3.2] // fatal error: recursive template instantiation exceeded maximum depth of 512 }
ç¬å°å±ã§ã®ã³ã³ãã¤ã«çµæâ [Wandbox]ä¸ã¸( ã¸ÕਠÕ)㸠ï¾ï½¯ï¾ï½¯ http://melpon.org/wandbox/permlink/KabKOkFRecUo1eD1
f() 㯠g() ãå¼ã³åºããg() 㯠f() ãå¼ã³åºãããç¸äºå帰ã¨ãªãããããã¤ã³ã¹ã¿ã³ã¹åãããã·ã°ããã£ã¯ãããã f(int const&) 㨠g(int const&) ã§ãããå帰ã«ãã£ã¦å¤åããªãããã®ãããã®ã³ã¼ãã¯è¦æ ¼çã«ãã¤ã³ã¹ã¿ã³ã¹åã«ããã¦åé¡ã¯ãªããGCC ã§ãåé¡ãªãã³ã³ãã¤ã«ãéããã«ãããããã Clang ã§ã¯ãã³ãã¬ã¼ãã¤ã³ã¹ã¿ã³ã¹åã®å¦çãç¡éã«å帰ãã¦åæ¢ãã¦ããªãããã¨ã©ã¼ã«ãªã£ã¦ãããããã¯æ確ã«å¦çç³»ã®ãã°ã§ãããClang 3.2 ãã 3.7(trunk) ç¾å¨ã«ãããã¾ã§ä¿®æ£ããã¦ããªãã
ãã®ç¸äºå帰ãã°ã«å¯¾ãã¦ã©ã®ãããªã¯ã¼ã¯ã¢ã©ã¦ã³ããæ¸ããããã£ã¨ãåç´ãªæã¯ããã³ãã¬ã¼ãã¤ã³ã¹ã¿ã³ã¹åã®æ·±ããã«ã¦ã³ããã¦ãããããã決ããåæ°ã«éããã SFINAE ã§ã¤ã³ã¹ã¿ã³ã¹åãæã¡åããã¨ã ãä¾ãã°ä¸è¨ã³ã¼ãã¯ä»¥ä¸ã®ããã«ã¯ã¼ã¯ã¢ã©ã¦ã³ããæ¸ããã¨ãã§ããã
#include <type_traits> #include <stdexcept> #define LIMIT 256 extern void* enabler; template<int D = 16, typename T, typename std::enable_if<(D < LIMIT - 1)>::type*& = enabler> constexpr T f(T const&); template<int D = 16, typename T, typename std::enable_if<!(D < LIMIT - 1)>::type*& = enabler> constexpr T f(T const&) { return std::runtime_error("recursive template instantiation exceeded maximum depth"), T(); } template<int D = 16, typename T, typename std::enable_if<(D < LIMIT - 1)>::type*& = enabler> constexpr T g(T const&); template<int D = 16, typename T, typename std::enable_if<!(D < LIMIT - 1)>::type*& = enabler> constexpr T g(T const&) { return std::runtime_error("recursive template instantiation exceeded maximum depth"), T(); } template<int D, typename T, typename std::enable_if<(D < LIMIT - 1)>::type*&> constexpr T f(T const& val) { return g<D + 1>(val); } template<int D, typename T, typename std::enable_if<(D < LIMIT - 1)>::type*&> constexpr T g(T const& val) { return val >= 10 ? val : f<D + 1>(val + 1); } int main() { constexpr auto x = f(0); }
ç¬å°å±ã§ã®ã³ã³ãã¤ã«çµæâ [Wandbox]ä¸ã¸( ã¸ÕਠÕ)㸠ï¾ï½¯ï¾ï½¯ http://melpon.org/wandbox/permlink/kePnBBddZLlZQcxo
ãã³ãã¬ã¼ãå¼æ° D ã¯æ·±ãã®ã«ã¦ã³ã¿ã§ãããã¤ã³ã¹ã¿ã³ã¹åã®æ·±ãããªãããã«éããã¨ãSFINAE ã«ãã£ã¦ã©ã³ã¿ã¤ã ã¨ã©ã¼ä¾å¤ãæããçãé¸æãããããã®ç㯠f() ã¾ã㯠g() ããã以ä¸å¼ã³åºããªããããã¤ã³ã¹ã¿ã³ã¹åã¯ããã§åæ¢ããããå®éã®ãå¼ã³åºããæ·±ãå¶éãè¶ããªããããã¯ã³ã³ãã¤ã«ã¨ã©ã¼ã«ãªããªãããã®ããã«ã㦠Clang ã®ç¸äºå帰ãã°ãåé¿ã§ããã
ï¼ãªããããæ·±ãå¶éãè¶ ãã¦ãå®éã®ãå¼ã³åºãããããªãããå ´åããããã³ã³ãã¤ã«æã§ããã° throw å¼ï¼å®æ°å¼ã§ãªãï¼ãè©ä¾¡ããã³ã³ãã¤ã«ã¨ã©ã¼ã«ãªããå®è¡æã§ããã°ä¾å¤ãæããããï¼
ãã®ã¯ã¼ã¯ã¢ã©ã¦ã³ãã®åé¡ç¹ã¯è¦ã¦ã®ã¨ããã³ã¼ããé常ã«é·ãéããªããã¨ã ãé¢æ°ãåããã ãã§ãªããããããã«ã«ã¦ã³ã¿ã¨ enable_if ãåãè¾¼ã¾ãªããã°ãªããªããç¸äºå帰ã f() â g() â f() ã®ãµãã¤ã®éã ãã§ãªã f() â g() â h() â i() â f() ã®ããã«å¤ãã®ä¸éé¢æ°ãä»ãããªãã°ããã®ãã¹ã¦ã«åæ§ã®ã¯ã¼ã¯ã¢ã©ã¦ã³ããä»è¾¼ãå¿
è¦ããããä¾ãã°æ¬¡ã®ããã«ã
Github:
ããã¯æªå¤¢ã§ãããªãã
éãã¯ã¼ã¯ã¢ã©ã¦ã³ããæ¸ããªãæ¹æ³
ããå¯è½ã§ããã°ãç¸äºå帰ãé¿ãããããªå®è£ ããã£ã¨ãæã¾ãããè¨è¨ä¸åé¿ã§ããªãå ´åããããããã§ãªãå ´åããããconstexpr é¢æ°ã®å®è£ ã§ç¸äºå帰ãåºç¾ããã®ã¯ãC++11 constexpr ã®å¶éä¸ã§è¤éãªã«ã¼ããè¨è¿°ããã¨ãã«å¤ãããã®ãããªã±ã¼ã¹ã§ç¸äºå帰ãã®ãã®ãåé¿ã§ããå®è£ ã®ã¢ã¤ãã£ã¢ãæè¿æãã¤ããã
sprout::while_loop ãããã ã
Github:
while_loop() ã¯å¼æ°ã¨ãã¦ï¼ç¶æ
ã®åæå¤ãã«ã¼ãçµäºãå¤å®ããåè¿°é¢æ°ã次ã®ç¶æ
ãè¿ãåé
ãªãã¬ã¼ã¿ï¼ãã¨ããåå㯠while_loop ã ãæåã«ããã¦ã¯ for æã«è¿ããå¦çã®å
é¨ã§ã¯ã«ã¼ããäºåæ¢ç´¢çãªåå²çµ±æ²»ã¨ãã¦è¡ããï¼ãã®ã¤ãã£ãªã ãååå帰ã¨å¼ã¶ï¼ãç¸äºå帰ã¯ç¾ããªããå¤éã«ã¼ãããªãã¬ã¼ã¿å
ããã®æ´ãªã while_loop å¼ã³åºãã¨ãã¦è¨è¿°ããããããç¸äºå帰ãå¿
è¦ã¨ããªããæè¿å®è£
ãããã®ãªã®ã§ä½¿ç¨ä¾ã¯å°ãªããã以ä¸ã®ããã«ä½¿ãã
Github:
ã¾ããç¸äºå帰ãé¿ããããã ãã§ãªããconstexpr ã§ã®ã«ã¼ãã®å®è£
ã®ããã« fun_impl_1(), fun_impl_2(), ... ã¨ãã£ãå®è£
ç¨é¢æ°ãä¹±ç«ããã®ãé²ãæå³ã§ãå¹æãããã¨æãããã
ã³ã³ãã¤ã©æ¯ã® constexpr é¢ä¿ã®ãã°ã¨ã¯ã¼ã¯ã¢ã©ã¦ã³ãã«ã¤ãã¦
以ä¸ã«æ¸ãçãã¦ãããã¨ã«ãã¦ããã
Sprout C++ Library Wiki: ã³ã³ãã¤ã©æ§è½æ¯è¼ http://www.boleros.x0.com/doc/sproutwiki/index.php?%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9%E6%80%A7%E8%83%BD%E6%AF%94%E8%BC%83
ããçç¡ç²¾ãªã®ã§ä¸»è¦ãªããã¤ãããè¨ãã¦ããªããææ°ã® VC++ çã®æ¤è¨¼ã¯é²ãã§ããªãããã®ãã¡å å®ãããããã¤ã«ãªããããããªããconstexpr ã«æããæå¿ã«ã¯å çãé¡ãããã