您的位置:首页 > 编程语言 > C语言/C++

C++11新特性应用--占位符(std::placeholders std::is_placeholder std::is_bind_expression)

2016-01-07 21:22 323 查看
http://blog.csdn.net/wangshubo1989/article/details/50471709

上一篇博客讲了std::function和std::bind的使用,其中提到了占位符,std::placeholders

定义如下:
<code class="hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">namespace placeholders {
extern /* unspecified */ _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
extern /* unspecified */ _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;
extern /* unspecified */ _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>;
// <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>


This namespace declares an unspecified number of objects: _1, _2, _3,…, which are used to specify placeholders in calls to function bind.

When the function object returned by bind is called, an argument with placeholder _1 is replaced by the first argument in the call, _2 is replaced by the second argument in the
<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">namespace</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::placeholders;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> bound_fn = <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::bind (fn,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>,_1);
bound_fn(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>);  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// calls fn(100,5), i.e.: replacing _1 by the first argument: 5 </span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>


The type of these placeholder objects is unspecified (it depends on the library implementation, see is_placeholder), but in all cases their type shall at least be nothrow default-constructible and nothrow copy-constructible. Whether assignment operations or
additional constructors are supported is implementation-defined, but any copy-assignment or move-constructor shall also be not throwing.

When a call to bind is used as a subexpression in another call to bind, the placeholders are relative to the outermost bind expression.
<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <functional></span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <string></span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <iostream></span>

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> goodbye(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">string</span>& s)
{
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Goodbye "</span> << s << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'\n'</span>;
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> Object {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> hello(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">string</span>& s)
{
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Hello "</span> << s << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'\n'</span>;
}
};

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> argc, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>* argv[])
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::function<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">string</span>&)> ExampleFunction;
Object instance;
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">string</span> str(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"World"</span>);
ExampleFunction f = <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::bind(&Object::hello, &instance,
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::placeholders::_1);

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// equivalent to instance.hello(str)</span>
f(str);
f = <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::bind(&goodbye, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::placeholders::_1);

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// equivalent to goodbye(str)</span>
f(str);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li></ul>


C++11还有一个std::is_placeholder:

作用为:

identifies whether T is a bind placeholder.

就是判断T是否为占位符!!

std::is_placeholder具有一个成员变量:value

If T is the type of a placeholder:

T is the placeholder’s order number (1 for _1, 2 for _2, …).

else

T is 0
<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <iostream>     <span class="hljs-comment" style="box-sizing: border-box;">// std::cout, std::boolalpha</span></span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <functional>   <span class="hljs-comment" style="box-sizing: border-box;">// std::is_placeholder, std::placeholders</span></span>

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main () {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">namespace</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::placeholders;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// introduces _1</span>

<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::is_placeholder<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">decltype</span>(_1)>::value << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'\n'</span>;
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::is_placeholder<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">decltype</span>(_2)>::value << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'\n'</span>;
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::is_placeholder<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>>::value << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'\n'</span>;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
}
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//输出:</span>
<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>
<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>
<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>


接下来就再解释一个:

std::is_bind_expression

用来判断是否为bind表达式:

同样具有value成员:
<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <iostream>     <span class="hljs-comment" style="box-sizing: border-box;">// std::cout, std::boolalpha</span></span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <functional>   <span class="hljs-comment" style="box-sizing: border-box;">// std::bind, std::plus, std::placeholders, std::is_bind_expression</span></span>

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main () {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">namespace</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::placeholders;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// introduces _1</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> increase_int = <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::bind (<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::plus<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>>(),_1,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);

<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::boolalpha;
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::is_bind_expression<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">decltype</span>(increase_int)>::value << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'\n'</span>;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
}
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//输出</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>


唯一需要注意的就是,这个返回的是true或是false,与is_placeholder有点区别~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: