{"id":1864,"date":"2018-10-23T17:37:23","date_gmt":"2018-10-23T09:37:23","guid":{"rendered":"https:\/\/damogame.cn:15443\/wordpress\/?p=1864"},"modified":"2018-10-25T08:33:48","modified_gmt":"2018-10-25T00:33:48","slug":"c%e7%9a%84%e6%9d%82%e4%b8%83%e6%9d%82%e5%85%ab%ef%bc%9aconstexpr%e4%b8%8e%e7%bc%96%e8%af%91%e6%9c%9f%e8%ae%a1%e7%ae%97","status":"publish","type":"post","link":"https:\/\/i007.cc\/wordpress\/archives\/1864","title":{"rendered":"C++\u7684\u6742\u4e03\u6742\u516b\uff1aconstexpr\u4e0e\u7f16\u8bd1\u671f\u8ba1\u7b97"},"content":{"rendered":"<div class=\"article-header-box\">\n<div class=\"article-header\">\n<div class=\"article-title-box\"><\/div>\n<div class=\"article-info-box\">\n<div class=\"operating\">\u7248\u6743\u58f0\u660e\uff1a\u672c\u6587\u4e3a\u535a\u4e3b\u539f\u521b\u6587\u7ae0\uff0c\u91c7\u7528\u77e5\u8bc6\u5171\u4eab \u7f72\u540d-\u975e\u5546\u4e1a\u6027\u4f7f\u7528-\u76f8\u540c\u65b9\u5f0f\u5171\u4eab 4.0 \u56fd\u9645 \u8bb8\u53ef\u534f\u8bae\u8fdb\u884c\u8bb8\u53ef\u3002 https:\/\/blog.csdn.net\/tangxiaoyin\/article\/details\/80123024<\/div>\n<\/div>\n<\/div>\n<\/div>\n<article>\n<div id=\"article_content\" class=\"article_content clearfix csdn-tracking-statistics\" data-pid=\"blog\" data-mod=\"popu_307\" data-dsm=\"post\">\n<div class=\"markdown_views\">\n<h3><a name=\"t0\"><\/a>\u5f15\u8a00<\/h3>\n<p>\u793e\u533a\uff08<a href=\"http:\/\/purecpp.org\/\" target=\"_blank\" rel=\"nofollow noopener\">http:\/\/purecpp.org\/<\/a>\uff09\u91cc\u6709\u670b\u53cb\u63d0\u51fa\u4e86\u7f16\u8bd1\u671f\u5206\u5272\u5b57\u7b26\u4e32\u7684\u9700\u6c42\uff0c\u5927\u5bb6\u5728\u7fa4\u91cc\u8fdb\u884c\u4e86\u70ed\u70c8\u7684\u8ba8\u8bba\uff0c\u4e5f\u505a\u4e86\u8bb8\u591a\u5c1d\u8bd5\uff0c\u4f46\u5e76\u6ca1\u6709\u5f97\u51fa\u786e\u5b9a\u7684\u7ed3\u679c\u3002\u672c\u6587\u4f5c\u8005\u8bd5\u56fe\u5bf9C++11\/14\u91cc\u7684\u65b0\u5173\u952e\u5b57constexpr\u8fdb\u884c\u7f16\u8bd1\u671f\u8ba1\u7b97\u7684\u603b\u7ed3\u548c\u63a2\u8ba8\uff0c\u5e76\u5728\u6700\u540e\u7ed3\u5408constexpr\u7ed9\u51faC++\u5728\u7f16\u8bd1\u671f\u5206\u5272\u5b57\u7b26\u4e32\u7684\u65b9\u6cd5\u3002<\/p>\n<h3><a name=\"t1\"><\/a>\u4e00\u3001\u7f16\u8bd1\u671f\u8ba1\u7b97<\/h3>\n<p>\u6211\u4eec\u5148\u6765\u770b\u4e00\u6bb5\u6c42\u9636\u4e58\uff08factorial\uff09\u7684\u7b97\u6cd5\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">size_t factorial(size_t n) noexcept\r\n{\r\n    return (n == 0) ? 1 : n * factorial(n - 1);\r\n}<\/pre>\n<p>\u5f88\u660e\u663e\uff0c\u8fd9\u662f\u4e00\u6bb5\u8fd0\u884c\u671f\u7b97\u6cd5\u3002\u7a0b\u5e8f\u8fd0\u884c\u7684\u65f6\u5019\uff0c\u4f20\u9012\u4e00\u4e2a\u503c\uff0c\u5b83\u53ef\u4ee5\u662f\u4e00\u4e2a\u53d8\u91cf\uff0c\u4e5f\u53ef\u4ee5\u662f\u4e00\u4e2a\u5e38\u91cf\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">int main(void)\r\n{\r\n    std::cout &lt;&lt; factorial(10) &lt;&lt; std::endl;\r\n    return 0;\r\n}<\/pre>\n<p>\u5982\u679c\u7a0b\u5e8f\u4ec5\u4ec5\u50cf\u8fd9\u6837\u4f20\u9012\u5e38\u91cf\uff0c\u6211\u4eec\u53ef\u80fd\u4f1a\u5e0c\u671b\u80fd\u591f\u8ba9\u5b83\u5b8c\u5168\u5728\u7f16\u8bd1\u7684\u65f6\u5019\u5c31\u628a\u7ed3\u679c\u8ba1\u7b97\u51fa\u6765\uff0c\u90a3\u4e48\u4ee3\u7801\u6539\u6210\u8fd9\u6837\u6216\u8bb8\u662f\u4e2a\u4e0d\u9519\u7684\u9009\u62e9\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">template &lt;size_t N&gt;\r\nstruct factorial\r\n{\r\n    enum : size_t { value = N * factorial&lt;N - 1&gt;::value };\r\n};\r\n\r\ntemplate &lt;&gt;\r\nstruct factorial&lt;0&gt;\r\n{\r\n    enum : size_t { value = 1 };\r\n};\r\n\r\nint main(void)\r\n{\r\n    std::cout &lt;&lt; factorial&lt;10&gt;::value &lt;&lt; std::endl;\r\n    return 0;\r\n}<\/pre>\n<p>\u53ea\u662f\u7528\u8d77\u6765\u4f1a\u7a0d\u663e\u9ebb\u70e6\u70b9\uff0c\u4f46\u597d\u5904\u662f\u8fd0\u884c\u671f\u6ca1\u6709\u4efb\u4f55\u65f6\u95f4\u4ee3\u4ef7\u3002<\/p>\n<p>\u50cf\u4e0a\u9762\u8fd9\u79cd\u8fd0\u7528\u6a21\u677f\u7684\u505a\u6cd5\uff0c\u7b97\u662f\u6700\u7b80\u5355\u7684\u6a21\u677f\u5143\u7f16\u7a0b\u4e86\u3002\u5bf9C++\u6a21\u677f\u6765\u8bf4\uff0c\u7c7b\u578b\u548c\u503c\u662f\u540c\u4e00\u79cd\u4e1c\u897f\uff1b\u540c\u65f6\uff0c\u53c8\u7531\u4e8eC++\u7684\u6a21\u677f\u6709\u4e86\u201cPattern Matching\u201d\uff08\u5373\u7279\u5316\u548c\u504f\u7279\u5316\uff09\uff0c\u540c\u65f6\u53c8\u5141\u8bb8\u6a21\u677f\u7684\u9012\u5f52\u7ed3\u6784\uff08\u89c1\u4e0a\u9762factorial\u4e2d\u4f7f\u7528factorial\u7684\u60c5\u51b5\uff09\uff0c\u4e8e\u662fC++\u7684\u6a21\u677f\u662f\u56fe\u7075\u5b8c\u5168\u7684\u4e00\u79cd\u72ec\u7acb\u4e8eC++\u7684\u8bed\u8a00\u3002\u7406\u8bba\u4e0a\u6765\u8bf4\uff0c\u6211\u4eec\u53ef\u4ee5\u5229\u7528\u5b83\u5728\u7f16\u8bd1\u671f\u5b8c\u6210\u6240\u6709\u8ba1\u7b97\u2014\u2014\u524d\u63d0\u662f\u8fd9\u4e9b\u8ba1\u7b97\u7684\u8f93\u5165\u90fd\u662fliteral\u7684\u3002<\/p>\n<h3><a name=\"t2\"><\/a>\u4e8c\u3001C++11\u4ee5\u540e\u7684\u65b0\u9650\u5b9a\u7b26\uff1aconstexpr<\/h3>\n<p>\u4eceC++11\u5f00\u59cb\uff0c\u6211\u4eec\u6709\u4e86constexpr specifier\u3002\u5b83\u53ef\u4ee5\u88ab\u7528\u4e8e\u53d8\u91cf\uff0c\u53ca\u51fd\u6570\u4e0a\uff0c\u50cf\u8fd9\u6837\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">template &lt;size_t N&gt;\r\nstruct t_factorial_\r\n{\r\n    enum : size_t { value = N * t_factorial_&lt;N - 1&gt;::value };\r\n};\r\n\r\ntemplate &lt;&gt;\r\nstruct t_factorial_&lt;0&gt;\r\n{\r\n    enum : size_t { value = 1 };\r\n};\r\n\r\ntemplate &lt;size_t N&gt;\r\nconstexpr auto t_factorial = t_factorial_&lt;N&gt;::value;\r\n\r\nint main(void)\r\n{\r\n    std::cout &lt;&lt; t_factorial&lt;10&gt; &lt;&lt; std::endl;\r\n    return 0;\r\n}<\/pre>\n<p>\u5f53\u7136\u4e86\uff0c\u4e0a\u9762\u66f4\u76f4\u63a5\u7684\u7528\u6cd5\u662f\u8fd9\u6837\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">constexpr size_t c_factorial(size_t n) noexcept\r\n{\r\n    return (n == 0) ? 1 : n * c_factorial(n - 1);\r\n}<\/pre>\n<p>\u5728C++11\u4e2d\uff0cconstexpr\u8fd8\u6709\u8bf8\u591a\u9650\u5236\uff0c\u4f46\u5230\u4e86C++14\uff0c\u5b83\u4f3c\u4e4e\u6709\u70b9\u8fc7\u4e8e\u5f3a\u5927\u4e86\u3002\u6bd4\u5982\u6211\u4eec\u53ef\u4ee5\u5728\u51fd\u6570\u4e2d\u5199\u591a\u884c\u8bed\u53e5\uff0c\u5b9a\u4e49\u53d8\u91cf\uff0c\u751a\u81f3\u662f\u5faa\u73af\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">\/\/ runtime version\r\ntemplate &lt;typename T, size_t N&gt;\r\nsize_t r_count(T&amp;&amp; v, const T(&amp;arr)[N]) noexcept\r\n{\r\n    size_t r = 0;\r\n    for (const auto&amp; a : arr) if (v == a) ++r;\r\n    return r;\r\n}\r\n\r\n\/\/ constexpr version\r\ntemplate &lt;typename T, size_t N&gt;\r\nconstexpr size_t c_count(T&amp;&amp; v, const T(&amp;arr)[N]) noexcept\r\n{\r\n    size_t r = 0;\r\n    for (const auto&amp; a : arr) if (v == a) ++r;\r\n    return r;\r\n}<\/pre>\n<p>\u5c31\u5982\u540c\u6211\u4eec\u5728\u5199\u7684\u53ea\u662f\u4e00\u4e2a\u666e\u901a\u51fd\u6570\uff0c\u4e4b\u540e\u5728\u51fd\u6570\u7684\u6700\u524d\u9762\u52a0\u4e0aconstexpr\u5b83\u9a6c\u4e0a\u5c31\u53ef\u4ee5\u5728\u7f16\u8bd1\u671f\u6267\u884c\u4e86\u3002<\/p>\n<p>constexpr\u540c\u6837\u5e26\u6765\u4e86\u5f3a\u5927\u7684\u7c7b\u578b\u8ba1\u7b97\u80fd\u529b\u3002\u6211\u4eec\u7b80\u5355\u7684\u6765\u770b\u4e2a\u4f8b\u5b50\uff0c\u5b9e\u73b0\u4e00\u4e2a\u201ctypes_insert\u201d\uff08Reference\uff1a<a href=\"http:\/\/darkc.at\/cxx-type-list\/\" target=\"_blank\" rel=\"nofollow noopener\">C++\u7684\u6742\u4e03\u6742\u516b\uff1a\u4f7f\u7528\u6a21\u677f\u5143\u7f16\u7a0b\u64cd\u4f5c\u7c7b\u578b\u96c6\u5408<\/a>\uff09\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">template &lt;typename...&gt;\r\nstruct types {};\r\n\r\ntemplate &lt;typename T, typename... U&gt;\r\nconstexpr auto insert(types&lt;U...&gt;) noexcept\r\n{\r\n    return types&lt;T, U...&gt;{};\r\n}<\/pre>\n<p>\u53ef\u4ee5\u770b\u5230\uff0c\u5bf9\u4e8e\u8fd9\u79cd\u7b80\u5355\u7684\u7c7b\u578b\u8ba1\u7b97\uff0cconstexpr\u6bd4\u6a21\u677f\u5143\u7684\u5b9e\u73b0\u8981\u6e05\u6670\u5f88\u591a\u3002<br \/>\n\u4e0d\u8fc7\uff0c\u7531\u4e8e\u51fd\u6570\u6a21\u677f\u7f3a\u5c11\u504f\u7279\u5316\uff0c\u56e0\u6b64\u9700\u8981\u7f16\u8bd1\u671f\u5206\u652f\u5224\u65ad\u7684\u201ctypes_assign\u201d\u662f\u6ca1\u529e\u6cd5\u76f4\u63a5\u5199\u51fa\u6765\u7684\uff08\u5728\u8fd9\u91cc\u65e0\u6cd5\u77ed\u8def\u6c42\u503c\u7684std::conditional\u5e76\u6ca1\u6709\u4ec0\u4e48\u7528\uff09\u3002\u8981\u77e5\u9053\uff0c\u51fd\u6570\u91cd\u8f7d\u867d\u7136\u5f3a\u5927\uff0c\u4f46\u4ec5\u80fd\u505a\u7f16\u8bd1\u671f\u7c7b\u578b\uff0c\u800c\u4e0d\u662f\u6570\u503c\u7684Pattern Matching\uff0c\u8fd9\u70b9\u662f\u4e0d\u5982\u7c7b\u6a21\u677f\u7684\u504f\u7279\u5316\/\u7279\u5316\u7684\u3002<\/p>\n<p>\u4e0d\u8fc7\u6211\u4eec\u53ef\u4ee5\u5229\u7528\u7c7b\u6a21\u677f\u7684\u504f\u7279\u5316\u6765\u6a21\u62df\u51fd\u6570\u6a21\u677f\u7684\u504f\u7279\u5316\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">template &lt;int N, typename T&gt;\r\nstruct impl_\r\n{\r\n    constexpr static auto assign(void) noexcept\r\n    {\r\n        return insert&lt;T&gt;(impl_&lt;N - 1, T&gt;::assign());\r\n    }\r\n};\r\n\r\ntemplate &lt;typename T&gt;\r\nstruct impl_&lt;0, T&gt;\r\n{\r\n    constexpr static auto assign(void) noexcept\r\n    {\r\n        return types&lt;&gt;{};\r\n    }\r\n};\r\n\r\ntemplate &lt;int N, typename T&gt;\r\nconstexpr auto assign(void) noexcept\r\n{\r\n    return impl_&lt;N, T&gt;::assign();\r\n}<\/pre>\n<p>\u4f46\u662f\u8bf4\u5b9e\u8bdd\uff0c\u6211\u5e76\u4e0d\u559c\u6b22\u8fd9\u6837\uff0c\u8fd9\u79cd\u5199\u6cd5\u4e27\u5931\u4e86\u51fd\u6570\u6a21\u677f\u7684\u7b80\u6d01\u6027\u3002\u4e00\u822c\u6765\u8bf4\uff0c\u5927\u5bb6\u4e5f\u4e0d\u4f1a\u7528constexpr\u505a\u592a\u590d\u6742\u7684\u7c7b\u578b\u8ba1\u7b97\uff0c\u8fd9\u91cc\u53cd\u800c\u7528\u6a21\u677f\u5143\u6765\u505a\u4f1a\u66f4\u52a0\u6e05\u6670\u4e9b\u3002\u4ece\u4e0a\u9762\u53ef\u4ee5\u770b\u51fa\u6765\uff0c\u5728\u505a\u7c7b\u578b\u8ba1\u7b97\u7684\u65f6\u5019\uff0creturn\u8fd4\u56de\u7684\u6570\u503c\u5e76\u4e0d\u662f\u6211\u4eec\u9700\u8981\u7684\uff0c\u800c\u7c7b\u578b\u7ed3\u679c\u4e00\u822c\u4f1a\u7528decltype\u53d6\u51fa\u6765\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u4e0d\u4f7f\u7528constexpr\uff0c\u4ec5\u7528\u666e\u901a\u51fd\u6570\u90fd\u662f\u53ef\u4ee5\u7684\u3002<\/p>\n<p>\u771f\u6b63\u8ba9\u4eba\u773c\u524d\u4e00\u4eae\u7684\uff0c\u5e94\u8be5\u8fd8\u662f\u4e0a\u9762c_count\u7684\u5199\u6cd5\u3002\u5229\u7528\u6a21\u677f\u5143\u505a\u6570\u503c\u8ba1\u7b97\u5176\u5b9e\u662f\u5b83\u7684\u77ed\u677f\u3002\u64b0\u5199\u590d\u6742\u4e0d\u8bf4\uff0c\u8fd8\u6709\u4e0d\u5c11\u7684\u5c40\u9650\u6027\u3002<\/p>\n<p>\u6bd4\u5982c_count\u53ef\u4ee5\u8fd9\u6837\u7528\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">template &lt;size_t N&gt;\r\nstruct Foo { enum : size_t { value = N }; };\r\n\r\nint main(void)\r\n{\r\n    std::cout &lt;&lt; Foo&lt;c_count(',', \"1, 2, 3, 4, 5, 6, 7, 8, 9, 0\")&gt;::value &lt;&lt; std::endl;\r\n    return 0;\r\n}<\/pre>\n<p>\u800c\u6a21\u677f\u5143\u5bf9string literal\u8fd9\u7c7b\u6570\u503c\u505a\u8ba1\u7b97\u662f\u6bd4\u8f83\u9ebb\u70e6\u7684\uff0ctemplate non-type arguments\u88ab\u9650\u5236\u4e3a\u5e38\u6574\u6570\uff08\u5305\u62ec\u679a\u4e3e\uff09\uff0c\u6216\u6307\u5411\u5916\u90e8\u94fe\u63a5\u5bf9\u8c61\u7684\u6307\u9488\uff08\u4e25\u683c\u6765\u8bf4\u4e0d\u6b62\u8fd9\u8fd9\u4e9b\u3002Reference\uff1a<a href=\"http:\/\/en.cppreference.com\/w\/cpp\/language\/template_parameters\" target=\"_blank\" rel=\"nofollow noopener\">Template parameters and template arguments<\/a>\uff09\u3002<\/p>\n<h3><a name=\"t3\"><\/a>\u4e09\u3001constexpr\u6027\u80fd\u5b9e\u6d4b<\/h3>\n<p>\u7406\u8bba\u4e0a\u6765\u8bf4\uff0c\u5982\u679cconstexpr\u53d1\u6325\u4f5c\u7528\uff0c\u8fd0\u884c\u65f6\u662f\u6ca1\u6709\u6027\u80fd\u635f\u8017\u7684\u3002\u6211\u4eec\u7528\u4e00\u4e2a\u4f8b\u5b50\u6765\u6d4b\u8bd5\u4e0b\u5b9e\u9645\u7684\u6548\u679c\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">\/\/ https:\/\/github.com\/mutouyun\/capo\/blob\/master\/capo\/stopwatch.hpp\r\n#include \"stopwatch.hpp\"\r\n\r\nsize_t r_fib(size_t n) noexcept\r\n{\r\n    if (n == 0) return 0;\r\n    if (n == 1) return 1;\r\n    return r_fib(n - 1) + r_fib(n - 2);\r\n}\r\n\r\nconstexpr size_t c_fib(size_t n) noexcept\r\n{\r\n    if (n == 0) return 0;\r\n    if (n == 1) return 1;\r\n    return c_fib(n - 1) + c_fib(n - 2);\r\n}\r\n\r\ntemplate &lt;size_t N&gt; struct t_fib_ { enum : size_t { value = t_fib_&lt;N - 1&gt;::value + t_fib_&lt;N - 2&gt;::value }; };\r\ntemplate &lt;&gt; struct t_fib_&lt;0&gt; { enum : size_t { value = 0 }; };\r\ntemplate &lt;&gt; struct t_fib_&lt;1&gt; { enum : size_t { value = 1 }; };\r\ntemplate &lt;size_t N&gt;\r\nconstexpr auto t_fib = t_fib_&lt;N&gt;::value;\r\n\r\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n\r\nint main(void)\r\n{\r\n    constexpr size_t n = 40;\r\n    capo::stopwatch&lt;&gt; sw;\r\n\r\n    sw.start();\r\n    size_t r1 = r_fib(n);\r\n    std::cout &lt;&lt; r1 &lt;&lt; \": \" &lt;&lt; sw.elapsed&lt;std::chrono::milliseconds&gt;() &lt;&lt; \"ms\" &lt;&lt; std::endl;\r\n\r\n    sw.start();\r\n    size_t r2 = c_fib(n);\r\n    std::cout &lt;&lt; r2 &lt;&lt; \": \" &lt;&lt; sw.elapsed&lt;std::chrono::milliseconds&gt;() &lt;&lt; \"ms\" &lt;&lt; std::endl;\r\n\r\n    sw.start();\r\n    size_t r3 = t_fib&lt;n&gt;;\r\n    std::cout &lt;&lt; r3 &lt;&lt; \": \" &lt;&lt; sw.elapsed&lt;std::chrono::milliseconds&gt;() &lt;&lt; \"ms\" &lt;&lt; std::endl;\r\n\r\n    return 0;\r\n}<\/pre>\n<p>g++ -v\uff1aversion 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2)<\/p>\n<p>\u7f16\u8bd1\u547d\u4ee4\u884c\uff1ag++ -std=c++14 -O3 -I. .\/test.cpp<\/p>\n<p>\u6d4b\u8bd5\u7ed3\u679c\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">102334155: 363ms\r\n102334155: 364ms\r\n102334155: 0ms<code class=\"hljs http has-numbering\"><\/code><\/pre>\n<p>\u6d4b\u8bd5\u7ed3\u679c\u5e76\u4e0d\u7406\u60f3\u3002\u6309\u7406\u6765\u8bf4\uff0cc_fib\u5e94\u8be5\u548ct_fib\u4e00\u6837\u4e0d\u9700\u8981\u4efb\u4f55\u65f6\u95f4\u624d\u5bf9\u3002\u4e0b\u9762\u6211\u4eec\u5c1d\u8bd5\u4fee\u6539\u4e00\u4e0bc_fib\u7684\u6d4b\u8bd5case\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">sw.start();\r\nconst size_t r2 = c_fib(n);\r\nstd::cout &lt;&lt; r2 &lt;&lt; \": \" &lt;&lt; sw.elapsed&lt;std::chrono::milliseconds&gt;() &lt;&lt; \"ms\" &lt;&lt; std::endl;<\/pre>\n<p>\u6211\u4eec\u53ef\u4ee5\u770b\u5230\uff0c\u9a6c\u4e0a\uff0c\u6d4b\u8bd5\u7684\u7ed3\u679c\u53d1\u751f\u4e86\u53d8\u5316\uff0c\u8017\u65f6\u53d8\u4e3a0ms\u3002<\/p>\n<p>\u4ece\u5b9e\u6d4b\u4e0a\u6765\u770b\uff0c\u9664\u4e86const\u4e4b\u5916\uff0c\u5982\u679c\u628ar2\u6539\u4e3astatic\u53d8\u91cf\uff08\u5b9a\u4e49\u65f6\u9a6c\u4e0a\u521d\u59cb\u5316\uff0c\u56e0\u6b64c_fib\u53ea\u4f1a\u88ab\u8c03\u7528\u4e00\u6b21\u3002\u82e5\u662f\u5b9a\u4e49\u540e\u518d\u5bf9static\u53d8\u91cf\u8d4b\u503c\uff0c\u5219\u7ed3\u679c\u548c\u666e\u901a\u53d8\u91cf\u4e00\u6837\uff09\uff0c\u6216constexpr\u53d8\u91cf\uff0c\u6216\u8005\u4e0d\u8981r2\uff0c\u76f4\u63a5\u5c06r_fib(n)\u653e\u5728std::cout\u540e\u9762\u8f93\u51fa\u7ed3\u679c\uff0c\u5728\u8fd9\u4e9b\u60c5\u51b5\u90fd\u4f1a\u89e6\u53d1constexpr\u7684\u7f16\u8bd1\u671f\u8ba1\u7b97\u3002<\/p>\n<p>\u5f53\u7136\u4e86\uff0c\u5982\u679c\u50cf\u8fd9\u6837\u5199\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">template &lt;size_t N&gt;\r\nstruct Foo { enum : size_t { value = N }; };\r\n\r\nsize_t xx = Foo&lt;c_fib(40)&gt;::value;<code class=\"hljs cs has-numbering\"><\/code><\/pre>\n<p>\u6216\u8005\u8fd9\u6837\u5199\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">char cc[c_fib(n)];<code class=\"hljs scss has-numbering\"><\/code><\/pre>\n<p>\u662f\u4e00\u5b9a\u4f1a\u89e6\u53d1\u7f16\u8bd1\u671f\u8ba1\u7b97\u7684\u3002<\/p>\n<p>constexpr\u5e76\u4e0d\u4f1a\u5c3d\u53ef\u80fd\u7684\u8ba9expressions\u5728\u7f16\u8bd1\u671f\u6267\u884c\uff0c\u53ea\u662f\u8868\u793aexpressions\u80fd\u5728\u7f16\u8bd1\u671f\u6267\u884c\u3002\u81f3\u4e8e\u771f\u6b63\u6267\u884c\u7684\u65f6\u673a\u662f\u7f16\u8bd1\u671f\u8fd8\u662f\u8fd0\u884c\u671f\uff0c\u4f9d\u8d56\u7f16\u8bd1\u5668\u81ea\u5df1\u7684\u9009\u62e9\u3002\u89c1<a href=\"http:\/\/en.cppreference.com\/w\/cpp\/language\/constexpr\" target=\"_blank\" rel=\"nofollow noopener\">constexpr specifier (since C++11)<\/a>\uff1a<\/p>\n<blockquote><p>The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time. Such variables and functions can then be used where only compile time constant expressions are allowed (provided that appropriate function arguments are given).<\/p><\/blockquote>\n<p>\u53e6\u5916\uff0c\u9700\u8981\u6ce8\u610f\u7684\u4e00\u70b9\u662f\uff0c\u51fd\u6570\u7684\u53c2\u6570\u4e0d\u80fd\u88ab\u5b9a\u4e49\u4e3aconstexpr\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c\u6211\u4eec\u4e0d\u80fd\u5728\u7f16\u8bd1\u671f\u4f7f\u7528constexpr\u51fd\u6570\u7684\u53c2\u6570\uff0c\u54ea\u6015\u6211\u4eec\u7ed9\u5b83\u4f20\u9012\u7684\u53c2\u6570\u786e\u5b9e\u662f\u4e00\u4e2aliteral\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">constexpr size_t test(size_t n) noexcept\r\n{\r\n    return Foo&lt;n&gt;::value; \/\/ error: \u2018n\u2019 is not a constant expression\r\n}\r\n\r\nconst size_t xx = test(123);<\/pre>\n<p>\u81ea\u7136\uff0c\u8fd9\u6837\u4e5f\u662f\u4e0d\u884c\u7684\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">constexpr size_t cube(size_t n) noexcept\r\n{\r\n    constexpr size_t cp = c_power(n, 3); \/\/ error: \u2018n\u2019 is not a constant expression\r\n    return cp;\r\n}<\/pre>\n<p>\u7b80\u5355\u6765\u8bf4\uff1a<\/p>\n<ul>\n<li>\u9664\u4e86\u8bed\u6cd5\u4e0a\u7684\u5fc5\u987b\u4e4b\u5916\uff08\u6bd4\u5982\u5728\u6a21\u677f\u53c2\u6570\u4e0a\u4f7f\u7528\u51fd\u6570\uff09\uff0cconstexpr\u51fd\u6570\u662f\u5426\u5728\u7f16\u8bd1\u671f\u6267\u884c\uff0c\u53d6\u51b3\u4e8e\u7f16\u8bd1\u5668\u7684\u9009\u62e9\uff1b<\/li>\n<li>\u4e0d\u8bba\u8be5\u51fd\u6570\u662f\u5426\u5728\u7f16\u8bd1\u671f\u6267\u884c\uff0cconstexpr\u51fd\u6570\u91cc\uff0c\u53c2\u6570\u90fd\u53ea\u662f\u666e\u901a\u7684\u53d8\u91cf\u3002<\/li>\n<\/ul>\n<p>C++\u8fd9\u6837\u8bbe\u8ba1\u4f30\u8ba1\u662f\u8003\u8651\u5230constexpr\u51fd\u6570\u9700\u8981\u540c\u65f6\u5177\u5907\u7f16\u8bd1\u671f\u548c\u8fd0\u884c\u671f\u6267\u884c\u7684\u80fd\u529b\u5427\u3002\u5982\u679c\u6211\u4eec\u9700\u8981\u5728constexpr\u51fd\u6570\u5185\u4f7f\u7528\u7f16\u8bd1\u671f\u53c2\u6570\uff0c\u53ea\u80fd\u4f7f\u7528template non-type arguments\u4e86\u3002<\/p>\n<h3><a name=\"t4\"><\/a>\u56db\u3001constexpr\u7684\u5e94\u7528\uff1a\u5b9e\u73b0\u4e00\u4e2a\u7f16\u8bd1\u671f\u5b57\u7b26\u4e32split<\/h3>\n<p>constexpr\u53ef\u4ee5\u7528\u5728\u6784\u9020\u51fd\u6570\u4e0a\uff0c\u8fd9\u6837\u5b9a\u4e49\u7684\u7c7b\u53ef\u4ee5\u7528\u6765\u5b9a\u4e49constexpr\u5bf9\u8c61\uff0c\u50cf\u8fd9\u6837\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">struct Foo\r\n{\r\n    int i_ = 0;\r\n    constexpr Foo(void) noexcept {}\r\n};\r\n\r\ntemplate &lt;int&gt;\r\nstruct Bar {};\r\n\r\nconstexpr Foo foo;\r\nBar&lt;foo.i_&gt;{};<\/pre>\n<p>\u4e8e\u662f\uff0c\u6211\u4eec\u53ef\u4ee5\u5148\u5c1d\u8bd5\u5b9a\u4e49\u4e00\u4e2a\u7f16\u8bd1\u671f\u7684string\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">namespace literal {\r\n\r\ntemplate &lt;size_t N&gt;\r\nclass string\r\n{\r\n    char str_[N] = {};\r\n\r\npublic:\r\n    constexpr string(void) noexcept = default; \r\n    constexpr string(const char* str, size_t n) noexcept\r\n    {\r\n        for (size_t i = 0; i &lt; std::min(N, n); ++i)\r\n            str_[i] = str[i];\r\n    }\r\n\r\n    template &lt;size_t N_&gt;\r\n    constexpr string(const char(&amp; str)[N_]) noexcept\r\n        : string{ str, N_ }\r\n    {}\r\n\r\n    constexpr auto operator[](size_t n) const noexcept\r\n    {\r\n        if (n &gt;= N) return '\\0';\r\n        return str_[n];\r\n    }\r\n\r\n    constexpr size_t size(void) const noexcept\r\n    {\r\n        return N;\r\n    }\r\n\r\n    constexpr size_t length(void) const noexcept\r\n    {\r\n        size_t r = 0;\r\n        for (; r &lt; N; ++r)\r\n            if (str_[r] == '\\0') break;\r\n        return r;\r\n    }\r\n\r\n    constexpr auto begin(void) const noexcept\r\n    {\r\n        return str_;\r\n    }\r\n\r\n    constexpr auto end(void) const noexcept\r\n    {\r\n        return str_ + length();\r\n    }\r\n\r\n    constexpr const char* c_str(void) const noexcept\r\n    {\r\n        return str_;\r\n    }\r\n\r\n    constexpr size_t count(char c) const noexcept\r\n    {\r\n        size_t r = 0;\r\n        for (size_t i = 0; i &lt; length(); ++i)\r\n            if (c == str_[i]) ++r;\r\n        return r;\r\n    }\r\n\r\n    static const size_t npos = -1;\r\n\r\n    constexpr string substr(size_t pos, size_t len = -1) const noexcept\r\n    {\r\n        return { str_ + pos, std::min(length() - pos, len) };\r\n    }\r\n\r\n    constexpr size_t find(char c, size_t pos = 0) const noexcept\r\n    {\r\n        for (size_t i = pos; i &lt; length(); ++i)\r\n            if (c == str_[i]) return i;\r\n        return npos;\r\n    }\r\n};\r\n\r\n} \/\/ namespace literal<\/pre>\n<p>\u5728\u4e0a\u9762\u8fd9\u4e2a\u7c7b\u91cc\uff0c\u6211\u4eec\u5b9e\u73b0\u4e86\u4e00\u4e9b\u7b80\u5355\u7684\u5b57\u7b26\u4e32\u64cd\u4f5c\u3002\u5b83\u652f\u6301\u5728\u6784\u9020\u7684\u65f6\u5019\u4f20\u9012\u5b57\u7b26\u4e32\u5b57\u9762\u91cf\uff08string literal\uff09\uff0c\u4e4b\u540e\u53ef\u4ee5\u5728\u7f16\u8bd1\u671f\u5bf9\u5b57\u7b26\u4e32\u505acount\u3001substr\u548cfind\u3002<br \/>\n\u4f46\u662f\u8fd9\u6837\u5b9a\u4e49\u7684string\u662f\u4e00\u4e2a\u7c7b\u6a21\u677f\uff0c\u5176\u53c2\u6570N\u786e\u5b9a\u8d77\u6765\u6bd4\u8f83\u9ebb\u70e6\uff0c\u6211\u4eec\u53ef\u4ee5\u7ed9\u5b83\u5305\u88c5\u4e00\u5c42\uff0c\u8ba9\u4ee3\u7801\u5199\u8d77\u6765\u66f4\u8f7b\u677e\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">namespace literal {\r\n\r\ntemplate &lt;size_t N&gt;\r\nconstexpr string&lt;N&gt; make(const char(&amp; str)[N]) noexcept\r\n{\r\n    return { str };\r\n}\r\n\r\n} \/\/ namespace literal\r\n\r\nconstexpr auto str = literal::make(\"1,2,3,4,5\");<\/pre>\n<p>\u8981\u5b9e\u73b0split\uff0c\u6211\u4eec\u8fd8\u9700\u8981\u4e00\u4e2a\u7f16\u8bd1\u671f\u7684array\u5bf9\u8c61\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">namespace literal {\r\n\r\ntemplate &lt;size_t M, size_t N&gt;\r\nclass string_array\r\n{\r\n    typedef string&lt;N&gt; string_t;\r\n    string_t arr_[M];\r\n\r\npublic:\r\n    constexpr string_array(void) noexcept = default;\r\n\r\n    constexpr const string_t&amp; operator[](size_t n) const noexcept\r\n    {\r\n        return arr_[n];\r\n    }\r\n\r\n    constexpr const string_t* begin(void) const noexcept\r\n    {\r\n        return arr_;\r\n    }\r\n\r\n    constexpr const string_t* end(void) const noexcept\r\n    {\r\n        return arr_ + M;\r\n    }\r\n};\r\n\r\n} \/\/ namespace literal<\/pre>\n<p>\u6211\u4eec\u6ce8\u610f\u5230\uff0c\u4ee5\u4e0a\u4e24\u4e2a\u7c7b\u7684\u5185\u90e8\u5168\u90e8\u4f7f\u7528\u6570\u7ec4\uff0c\u800c\u4e0d\u662f\u6307\u9488\u6765\u5b58\u50a8\u5185\u5bb9\uff0c\u8fd9\u662f\u56e0\u4e3a\u60f3\u8981\u5bf9\u8c61\u80fd\u591f\u5728\u7f16\u8bd1\u671f\u88ab\u5b9a\u4e49\u51fa\u6765\uff0cC++\u8981\u6c42\u5176\u4e0d\u80fd\u6709non-trivial destructor\uff0c\u56e0\u6b64\u5bf9\u8c61\u81ea\u8eab\u662f\u4e0d\u80fd\u52a8\u6001\u5206\u914d\u5185\u5b58\u7684\u3002\u5982\u679c\u6211\u4eec\u4f7f\u7528\u6307\u9488\uff0c\u5c31\u53ea\u80fd\u7531\u5916\u90e8\u9884\u5148\u4f20\u9012\u4e00\u5757\u8db3\u591f\u5927\u7684\u5185\u5b58\u5757\u4f9b\u6211\u4eec\u4f7f\u7528\u4e86\u3002<br \/>\n\u5b9e\u9645\u4e0a\uff0c\u7531\u4e8e\u6211\u4eec\u53ea\u8003\u8651\u5bf9\u8c61\u5728\u7f16\u8bd1\u671f\u65f6\u7684\u521d\u59cb\u5316\u548c\u8ba1\u7b97\uff0c\u56e0\u6b64\u62f7\u8d1d\u7684\u5f00\u9500\u4e0d\u9700\u8981\u592a\u5728\u610f\u3002<\/p>\n<p>\u63a5\u4e0b\u6765\uff0c\u6211\u4eec\u53ef\u4ee5\u5b9e\u73b0split\u4e86\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">namespace literal {\r\n\r\ntemplate &lt;size_t M, size_t N&gt;\r\nclass string_array\r\n{\r\n    typedef string&lt;N&gt; string_t;\r\n    string_t arr_[M];\r\n\r\n    template &lt;size_t M_, size_t N_&gt;\r\n    friend constexpr string_array&lt;M_, N_&gt; split(char, const char(&amp;)[N_]) noexcept;\r\n\r\n    \/\/ ...\r\n};\r\n\r\ntemplate &lt;size_t M, size_t N&gt;\r\nconstexpr string_array&lt;M, N&gt; split(char delimiter, const char(&amp; str)[N]) noexcept\r\n{\r\n    string_array&lt;M, N&gt; r;\r\n    auto s = make(str);\r\n    size_t start = 0, end = s.find(delimiter);\r\n    for (size_t i = 0; i &lt; M; ++i)\r\n    {\r\n        r.arr_[i] = s.substr(start, end - start);\r\n        if (end == string&lt;N&gt;::npos) break;\r\n        start = end + 1;\r\n        end = s.find(delimiter, start);\r\n    }\r\n    return r;\r\n}\r\n\r\n} \/\/ namespace literal\r\n\r\n#define LITERAL_SPLIT(C, S) literal::split&lt;literal::make(S).count(C) + 1&gt;(C, S)\r\n\r\nint main(void)\r\n{\r\n    constexpr auto arr = LITERAL_SPLIT(',', \"1,2,3,4,5\");\r\n    for (auto&amp; s: arr)\r\n        std::cout &lt;&lt; s.c_str() &lt;&lt; std::endl;\r\n\r\n    return 0;\r\n}<\/pre>\n<p>\u5230\u6b64\u4e3a\u6b62\uff0c\u4e00\u4e2a\u7f16\u8bd1\u671f\u7684\u5b57\u7b26\u4e32split\u51fd\u6570\u5c31\u5b8c\u6210\u4e86\uff0c\u8f93\u5165\u53c2\u6570\u4e3a\u5b57\u7b26\u6570\u7ec4\uff0c\u8f93\u51fa\u4e3aliteral::string_array\u3002\u6211\u4eec\u8fd8\u53ef\u4ee5\u4e3aliteral::string_array\u6dfb\u52a0to_array\u7b49\u51fd\u6570\uff0c\u8ba9\u5b83\u652f\u6301\u8f6c\u6362\u4e3astd::array\u3002<\/p>\n<p>\u6ce8\u610f\uff0c\u4ee5\u4e0a\u4ee3\u7801\u4ec5\u5728g++ 5.3.1\u4e0a\u7f16\u8bd1\u901a\u8fc7\uff0cVS2015\u7531\u4e8e\u4e0d\u652f\u6301C++14\u7684constexpr\uff0c\u56e0\u6b64\u65e0\u6cd5\u7f16\u8bd1\u8fd9\u4e9b\u4ee3\u7801\u3002<\/p>\n<h3><a name=\"t5\"><\/a>\u4e94\u3001\u4f7f\u7528constexpr\u7b80\u5316\u7c7b\u578b\u8ba1\u7b97<\/h3>\n<p>\u4e0a\u6587\u7b2c2\u8282\uff0c\u6211\u63d0\u5230\u4e86\u53ef\u4ee5\u4f7f\u7528constexpr\u505a\u7b80\u5355\u7684\u7c7b\u578b\u8ba1\u7b97\u6765\u4ee3\u66ff\u6a21\u677f\u5143\u3002\u5728\u4e0d\u9700\u8981\u6570\u503c\u7279\u5316\u505a\u5206\u652f\u5224\u65ad\u7684\u60c5\u51b5\u4e0b\uff0cconstexpr\u51fd\u6570\u4f1a\u6bd4\u6a21\u677f\u5143\u7b80\u6d01\u5f88\u591a\u3002\u63a5\u4e0b\u6765\uff0c\u6211\u4eec\u5c1d\u8bd5\u6539\u5199\u4e00\u4e0b\u4e0a\u4e00\u8282\u7684split\uff0c\u4ec5\u4f7f\u7528C++11\u6807\u51c6\u4e0b\u7684constexpr\uff0c\u5e76\u901a\u8fc7\u7c7b\u578b\u8ba1\u7b97\u6765\u5b9e\u73b0\u7f16\u8bd1\u671f\u7684\u5b57\u7b26\u4e32\u5206\u5272\u3002<\/p>\n<p>\u60f3\u8981\u901a\u8fc7\u7c7b\u578b\u8ba1\u7b97\uff0c\u800c\u4e0d\u662f\u6570\u503c\u8ba1\u7b97\u6765\u5904\u7406\u5b57\u7b26\u4e32\u662f\u6bd4\u8f83\u9ebb\u70e6\u7684\u3002\u6211\u4eec\u9996\u5148\u8981\u5c1d\u8bd5\u628a\u5b57\u7b26\u4e32\u7c7b\u578b\u5316\u3002\u4f46\u662f\u5728C++\u4e2d\uff0cstring literal\u662f\u4e0d\u80fd\u4f5c\u4e3a\u6a21\u677f\u53c2\u6570\u7684\uff0c\u56e0\u6b64\u6211\u4eec\u628a\u5b57\u7b26\u4e32\u5b57\u9762\u91cf\u8f6c\u6362\u6210\u4e00\u4e2a\u4e2a\u7684char\uff0c\u7136\u540e\u5c06\u8fd9\u4e9bchar\u4f5c\u4e3a\u6a21\u677f\u53c2\u6570\u4f20\u9012\u8fdb\u53bb\u3002<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n\/\/ Define the literal string &amp; helper types\r\n\r\ntemplate &lt;char...&gt;\r\nstruct literal_string { static const char to_string[]; };\r\n\r\ntemplate &lt;char... S&gt;\r\nconst char literal_string&lt;S...&gt;::to_string[] = { S... };\r\n\r\ntemplate &lt;class... LS&gt;\r\nstruct literal_array { static const std::array&lt;std::string, sizeof...(LS)&gt; to_array; };\r\n\r\ntemplate &lt;class... LS&gt;\r\nconst std::array&lt;std::string, sizeof...(LS)&gt; literal_array&lt;LS...&gt;::to_array = { LS::to_string... };<\/pre>\n<p>\u8fd9\u91cc\u6211\u5728literal_array\u91cc\u76f4\u63a5\u4f7f\u7528\u4e86std::array\uff0c\u914d\u5408std::string\u6765\u5b58\u50a8\u7ed3\u679c\u3002\u81ea\u7136\uff0c\u4e5f\u53ef\u4ee5\u4f7f\u7528\u666e\u901a\u7684char\u6570\u7ec4\u6765\u5b58\u50a8\u3002<\/p>\n<p>\u9ebb\u70e6\u7684\u662f\uff0c\u6211\u4eec\u5982\u4f55\u628a\u4e00\u4e2a\u5b57\u7b26\u4e32\u5b57\u9762\u91cf\u8f6c\u6362\u6210literal_string<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">literal_string&lt;\"123\"[0], \"123\"[1], \"123\"[2]&gt;{};<\/pre>\n<p>\u53ef\u4ee5\u6ce8\u610f\u5230\uff0c\u8fd9\u91cc\u9700\u8981\u6211\u4eec\u5bf9\u5b57\u7b26\u4e32\u7684\u5b57\u7b26\u8ba1\u6570\uff0c\u7136\u540e\u987a\u6b21\u5c06\u6b64\u5b57\u7b26\u4e32\u5c55\u5f00\u5230\u6a21\u677f\u53c2\u6570\u4e0a\u3002<\/p>\n<p>\u5b8f\u5143\u662f\u6ca1\u529e\u6cd5\u5bf9\u5b57\u7b26\u4e32\u7684\u5185\u5bb9\u505a\u5206\u6790\u7684\uff1b\u800c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u7f16\u8bd1\u671f\u6280\u5de7\u5f97\u5230\u5b57\u7b26\u4e2a\u6570\uff0c\u5b8f\u4e5f\u6ca1\u6709\u529e\u6cd5\u5229\u7528\u8fd9\u4e2a\u7f16\u8bd1\u671f\u6570\u503c\u53bb\u505a\u8ba1\u7b97\u3002<\/p>\n<p>\u8fd9\u91cc\u6211\u4eec\u6709\u4e00\u4e2a\u7b80\u5355\u800c\u66b4\u529b\u7684\u89e3\u51b3\u65b9\u6cd5\uff0c\u5c31\u662f\u59cb\u7ec8\u8ba9\u5b8f\u5d4c\u5957\u8ba1\u7b97\u5230\u6700\u540e\u4e00\u5c42\uff0c\u5e76\u63d0\u4f9b\u4e00\u4e2aat\u51fd\u6570\uff0c\u5f53\u8ba1\u6570\u7684\u4e2a\u6570\u8d85\u51fa\u5b57\u7b26\u4e32\u957f\u5ea6\u7684\u65f6\u5019\u8fd4\u56de\u2019\\0\u2019\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">#define CAPO_PP_MAX_                        256\r\n#define CAPO_PP_VA_(...)                    __VA_ARGS__ \/* Try to expand __VA_ARGS__ *\/\r\n#define CAPO_PP_PROXY_(F, ...)              CAPO_PP_VA_(F(__VA_ARGS__))\r\n\r\n#define CAPO_PP_REPEAT_0_(F1, F2, ...)\r\n#define CAPO_PP_REPEAT_1_(F1, F2, ...)      CAPO_PP_VA_(F1(1, __VA_ARGS__))\r\n#define CAPO_PP_REPEAT_2_(F1, F2, ...)      CAPO_PP_REPEAT_1_(F1, F2, __VA_ARGS__) CAPO_PP_VA_(F2(2, __VA_ARGS__))\r\n......\r\n#define CAPO_PP_REPEAT_256_(F1, F2, ...)    CAPO_PP_REPEAT_255_(F1, F2, __VA_ARGS__) CAPO_PP_VA_(F2(256, __VA_ARGS__))\r\n\r\n\/*\r\nCAPO_PP_REPEAT(5, f, data)\r\n--&gt;\r\nf(1, data) f(2, data) f(3, data) f(4, data) f(5, data)\r\n*\/\r\n\r\n#define CAPO_PP_REPEAT_P_(F, ...)           CAPO_PP_VA_(F(__VA_ARGS__))\r\n#define CAPO_PP_REPEATEX_(N, F1, F2, ...)   CAPO_PP_REPEAT_P_(CAPO_PP_JOIN_(CAPO_PP_REPEAT_, CAPO_PP_JOIN_(N, _)), F1, F2, __VA_ARGS__)\r\n#define CAPO_PP_REPEATEX_MAX_(F1, F2, ...)  CAPO_PP_REPEATEX_(CAPO_PP_MAX_, F1, F2, __VA_ARGS__)\r\n#define CAPO_PP_REPEAT_(N, F, ...)          CAPO_PP_REPEATEX_(N, F, F, __VA_ARGS__)\r\n#define CAPO_PP_REPEAT_MAX_(F, ...)         CAPO_PP_REPEATEX_MAX_(F, F, __VA_ARGS__)\r\n\r\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n\r\n\/* at *\/\r\n\r\ntemplate &lt;size_t N&gt;\r\nconstexpr auto at(size_t n, const char(&amp;str)[N]) noexcept\r\n{\r\n    return (n &lt; N) ? str[n] : '\\0';\r\n}\r\n\r\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n\/\/ Preprocessor\r\n\r\n#define LITERAL_C(N, STR)       , at(N, STR)\r\n#define LITERAL_S(STR)          literal_string&lt;at(0, STR) CAPO_PP_REPEAT_MAX_(LITERAL_C, STR)&gt;{}\r\n\u8fd9\u6837\uff0c\u6211\u4eec\u8c03\u7528LITERAL_S(\"123\")\uff0c\u5c31\u53ef\u4ee5\u5f97\u5230literal_string&lt;'1', '2', '3', '\\0', ...&gt;\u3002\u8fc8\u51fa\u4e86\u7b2c\u4e00\u6b65\u4ee5\u540e\uff0c\u540e\u9762\u7684\u7c7b\u578b\u8ba1\u7b97\u6211\u4eec\u5c31\u8f7b\u8f66\u719f\u8def\u4e86\uff1a\r\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n\/\/ Operations\r\n\r\n\/* link *\/\r\n\r\ntemplate &lt;char... S1, char... S2&gt;\r\nconstexpr auto link(literal_string&lt;S1...&gt;, literal_string&lt;S2...&gt;) noexcept\r\n{\r\n    return literal_string&lt;S1..., S2...&gt;{};\r\n}\r\n\r\ntemplate &lt;typename... LS1, typename... LS2&gt;\r\nconstexpr auto link(literal_array&lt;LS1...&gt;, literal_array&lt;LS2...&gt;) noexcept\r\n{\r\n    return literal_array&lt;LS1..., LS2...&gt;{};\r\n}\r\n\r\n\/* insert *\/\r\n\r\ntemplate &lt;bool Valid, char C, char... S&gt;\r\nconstexpr auto insert(literal_string&lt;S...&gt;) noexcept\r\n{\r\n    return typename std::conditional&lt;Valid, literal_string&lt;C, S...&gt;, literal_string&lt;S...&gt;&gt;::type{};\r\n}\r\n\r\n\/* remove *\/\r\n\r\ntemplate &lt;char V&gt;\r\nconstexpr auto remove(literal_string&lt;&gt;) noexcept\r\n{\r\n    return literal_string&lt;&gt;{};\r\n}\r\n\r\ntemplate &lt;char V, char C, char... S&gt;\r\nconstexpr auto remove(literal_string&lt;C, S...&gt;) noexcept\r\n{\r\n    return insert&lt;V != C, C&gt;(remove&lt;V&gt;(literal_string&lt;S...&gt;{}));\r\n}\r\n\r\n\/* replace *\/\r\n\r\ntemplate &lt;char V1, char V2&gt;\r\nconstexpr auto replace(literal_string&lt;&gt;) noexcept\r\n{\r\n    return literal_string&lt;&gt;{};\r\n}\r\n\r\ntemplate &lt;char V1, char V2, char C, char... S&gt;\r\nconstexpr auto replace(literal_string&lt;C, S...&gt;) noexcept\r\n{\r\n    return insert&lt;true, (V1 == C) ? V2 : C&gt;(replace&lt;V1, V2&gt;(literal_string&lt;S...&gt;{}));\r\n}\r\n\r\n\/* count *\/\r\n\r\ntemplate &lt;char V&gt;\r\nconstexpr size_t count(literal_string&lt;&gt;) noexcept\r\n{\r\n    return 0;\r\n}\r\n\r\ntemplate &lt;char V, char C, char... S&gt;\r\nconstexpr size_t count(literal_string&lt;C, S...&gt;) noexcept\r\n{\r\n    return ((V == C) ? 1 : 0) + count&lt;V&gt;(literal_string&lt;S...&gt;{});\r\n}\r\n\r\n\/* find *\/\r\n\r\nconstexpr size_t npos = static_cast&lt;size_t&gt;(-1);\r\n\r\ntemplate &lt;char V, size_t N = 0&gt;\r\nconstexpr size_t find(literal_string&lt;&gt;) noexcept\r\n{\r\n    return npos;\r\n}\r\n\r\ntemplate &lt;char V, size_t N = 0, char C, char... S&gt;\r\nconstexpr size_t find(literal_string&lt;C, S...&gt;) noexcept\r\n{\r\n    return (V == C) ? N : find&lt;V, N + 1&gt;(literal_string&lt;S...&gt;{});\r\n}\r\n\r\n\/* substr *\/\r\n\r\ntemplate &lt;size_t B, size_t E = npos, size_t N = 0&gt;\r\nconstexpr auto substr(literal_string&lt;&gt;) noexcept\r\n{\r\n    return literal_string&lt;&gt;{};\r\n}\r\n\r\ntemplate &lt;size_t B, size_t E = npos, size_t N = 0, char C, char... S&gt;\r\nconstexpr auto substr(literal_string&lt;C, S...&gt;) noexcept\r\n{\r\n    return insert&lt;(B &lt;= N) &amp;&amp; (N &lt; E), C&gt;(substr&lt;B, E, N + 1&gt;(literal_string&lt;S...&gt;{}));\r\n}<\/pre>\n<p>\u6700\u540e\uff0c\u6211\u4eec\u5b9e\u73b0literal_string\u7684split\uff0c\u5e76\u5b8c\u6210LITERAL_SPLIT\u5b8f\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">\/\/ split\r\n\r\n#if defined(_MSC_VER)\r\ntemplate &lt;char V, class LS&gt; struct find_ { enum: size_t { value = find&lt;V&gt;(LS{}) }; };\r\ntemplate &lt;char Sep, class LS, size_t = find_&lt;Sep, LS&gt;::value&gt; \/\/ VS2015\u5bf9constexpr\u51fd\u6570\u7684\u652f\u6301\u4e0d\u591f\u597d\uff0c\u4e0d\u80fd\u76f4\u63a5\u628aconstexpr\u51fd\u6570\u4f5c\u4e3a\u9ed8\u8ba4\u53c2\u6570\r\n#else\r\ntemplate &lt;char Sep, class LS, size_t = find&lt;Sep&gt;(LS{})&gt;\r\n#endif\r\nstruct split_;\r\n\r\ntemplate &lt;char Sep&gt;\r\nstruct split_&lt;Sep, literal_string&lt;&gt;, npos&gt;\r\n{\r\n    using type = literal_array&lt;&gt;;\r\n};\r\n\r\ntemplate &lt;char Sep, char... S&gt;\r\nstruct split_&lt;Sep, literal_string&lt;S...&gt;, npos&gt;\r\n{\r\n    using type = literal_array&lt;literal_string&lt;S...&gt;&gt;;\r\n};\r\n\r\ntemplate &lt;char Sep, size_t Pos, char... S&gt;\r\nstruct split_&lt;Sep, literal_string&lt;S...&gt;, Pos&gt;\r\n{\r\n    using head = decltype(substr&lt; 0, Pos&gt;(literal_string&lt;S...&gt;{}));\r\n    using tail = decltype(substr&lt;Pos + 1&gt;(literal_string&lt;S...&gt;{}));\r\n    using type = capo::types_link_t&lt;literal_array&lt;head&gt;, typename split_&lt;Sep, tail&gt;::type&gt;;\r\n};\r\n\r\ntemplate &lt;char Sep, char... S&gt;\r\nconstexpr auto split(literal_string&lt;S...&gt;) noexcept\r\n{\r\n    return typename split_&lt;Sep, literal_string&lt;S...&gt;&gt;::type{};\r\n}\r\n\r\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n\/\/ Preprocessor\r\n\r\n#define LITERAL_C(N, STR)       , at(N, STR)\r\n#define LITERAL_S(STR)          substr&lt;0, sizeof(STR)&gt;(literal_string&lt;at(0, STR) CAPO_PP_REPEAT_MAX_(LITERAL_C, STR)&gt;{})\r\n#define LITERAL_SPLIT(SEP, STR) decltype(split&lt;SEP&gt;(LITERAL_S(STR)))::to_array<\/pre>\n<p>\u4f7f\u7528\u65b9\u6cd5\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">auto arr = LITERAL_SPLIT(',', \"1,2,3,4,5,6,7,8,9,0\"); \/\/ std::array&lt;std::string, 10&gt;<\/pre>\n<p>\u4ee5\u4e0a\u4ee3\u7801\u5728g++ 5.3.1\u53caVS2015\u4e0a\u7f16\u8bd1\u901a\u8fc7\uff08VS2015\u91cc\u5b8f\u4e0d\u80fd\u5d4c\u5957\u8fd9\u4e48\u6df1\uff0c\u9700\u8981\u8c03\u6574CAPO_PP_MAX_\u7684\u503c\uff09\u3002<\/p>\n<p>\u8fd9\u4e2asplit\u5bf9\u6bd4\u4e0a\u4e00\u8282\u5b9e\u73b0\u7684\u6700\u5927\u7684\u597d\u5904\u662f\uff0c\u652f\u6301\u8fd0\u884c\u671f\u65e0\u635f\u8017\u7684\u628a\u5b57\u7b26\u4e32\u5b57\u9762\u91cf\u62c6\u5206\uff0c\u5e76\u653e\u5165std::string\u7684std::array\u4e2d\u3002<\/p>\n<p>\u7b2c5\u8282\u4ee3\u7801\u4e0b\u8f7d\uff1a<a href=\"https:\/\/github.com\/mutouyun\/cpp-literal-split\" target=\"_blank\" rel=\"nofollow noopener\">An example for spliting a string literal in compile-time<\/a>\u3002<\/p>\n<blockquote><p><strong>\u4f5c\u8005\u7b80\u4ecb\uff1a<\/strong><br \/>\n\u5f20\u8f76\uff0c\u73e0\u6d77\u5e02\u4e91\u521b\u79d1\u6280\u7814\u53d1\u4e2d\u5fc3\u9ad8\u7ea7\u8f6f\u4ef6\u5de5\u7a0b\u5e08\uff0c\u8d44\u6df1C++\u7231\u597d\u8005\u3002\u719f\u7ec3\u4f7f\u7528C++\uff0c\u67098\u5e74\u4ee5\u4e0a\u5f00\u53d1\u7ecf\u9a8c\uff0c\u64c5\u957f\u6cdb\u578b\/\u6a21\u677f\u5143\u7f16\u7a0b\u3002\u81f4\u529b\u4e8e\u5728\u5b9e\u9645\u9879\u76ee\u4e2d\u5e94\u7528\u548c\u63a8\u5e7f\u73b0\u4ee3C++ \u3002<br \/>\n<strong>\u5ba1\u6821\/\u8d23\u4efb\u7f16\u8f91\uff1a<\/strong>\u00a0\u5510\u5c0f\u5f15\uff08<a href=\"http:\/\/weibo.com\/txydonyin\" target=\"_blank\" rel=\"nofollow noopener\">@\u5510\u95e8\u6559\u4e3b<\/a>\uff09\uff0c\u79c9\u6301\u4ea4\u6d41\u3001\u5206\u4eab\u3001\u8fdb\u6b65\uff0c\u6b22\u8fce\u6280\u672f\u6295\u7a3f\u3001\u7ea6\u7a3f\uff0c\u7ed9\u6587\u7ae0\u7ea0\u9519\uff0c\u8bf7\u53d1\u9001\u90ae\u4ef6\u81f3<a href=\"mailto:tangxy@csdn.net\" target=\"_blank\" rel=\"nofollow noopener\">tangxy@csdn.net<\/a>\u3002<\/p><\/blockquote>\n<\/div>\n<\/div>\n<\/article>\n","protected":false},"excerpt":{"rendered":"<p>\u7248\u6743\u58f0\u660e\uff1a\u672c\u6587\u4e3a\u535a\u4e3b\u539f\u521b\u6587\u7ae0\uff0c\u91c7\u7528\u77e5\u8bc6\u5171<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"colormag_page_container_layout":"default_layout","colormag_page_sidebar_layout":"default_layout","footnotes":""},"categories":[],"tags":[119],"class_list":["post-1864","post","type-post","status-publish","format-standard","hentry","tag-03-"],"_links":{"self":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts\/1864","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/comments?post=1864"}],"version-history":[{"count":0,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts\/1864\/revisions"}],"wp:attachment":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/media?parent=1864"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/categories?post=1864"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/tags?post=1864"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}