{"id":4523,"date":"2009-04-22T13:06:00","date_gmt":"2009-04-22T13:06:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2009\/04\/22\/decltype-c0x-features-in-vc10-part-3\/"},"modified":"2019-02-18T18:45:56","modified_gmt":"2019-02-18T18:45:56","slug":"decltype-c0x-features-in-vc10-part-3","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/decltype-c0x-features-in-vc10-part-3\/","title":{"rendered":"decltype: C++0x Features in VC10, Part 3"},"content":{"rendered":"<p class=\"MsoNormal\"><span><a href=\"http:\/\/blogs.msdn.com\/vcblog\/archive\/2008\/10\/28\/lambdas-auto-and-static-assert-c-0x-features-in-vc10-part-1.aspx\"><font color=\"#0000ff\">Part 1<\/font><\/a> of this series covered <b>lambdas<\/b>, <b>auto<\/b>, and <b>static_assert<\/b>.<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><a href=\"http:\/\/blogs.msdn.com\/vcblog\/archive\/2009\/02\/03\/rvalue-references-c-0x-features-in-vc10-part-2.aspx\"><font color=\"#0000ff\">Part 2<\/font><\/a> of this series covered <b>rvalue references<\/b>, which enable <b>move semantics<\/b> and <b>perfect forwarding<\/b>.<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>Today, I&#8217;m going to talk about <b>decltype<\/b>, which allows perfect forwarding functions to have arbitrary return types.&nbsp; It&#8217;s of interest to people who are writing highly generic code.<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><b><span>the return type problem<\/p>\n<p><\/span><\/b><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>C++98\/03 has an interesting blind spot &#8211; given an expression like <\/span><span>x * y<\/span><span>, where <\/span><span>x<\/span><span> and <\/span><span>y<\/span><span> have arbitrary types, there&#8217;s no way to say &#8220;the type of <\/span><span>x * y<\/span><span>&#8220;.&nbsp; If <\/span><span>x<\/span><span> is of type <\/span><span>Watts<\/span><span> and <\/span><span>y<\/span><span> is of type <\/span><span>Seconds<\/span><span>, then <\/span><span>x * y<\/span><span> might be of type <\/span><span>Joules<\/span><span>.&nbsp; Given <\/span><span>print(const T&amp; t)<\/span><span>, you can call <\/span><span>print(x * y)<\/span><span>, and <\/span><span>T<\/span><span> will be deduced to be <\/span><span>Joules<\/span><span>, but this doesn&#8217;t work in reverse: when writing <\/span><span>multiply(const A&amp; a, const B&amp; b)<\/span><span>, you can&#8217;t name its return type while preserving full generality.&nbsp; Even though when <\/span><span>multiply&lt;A, B&gt;()<\/span><span> is instantiated, the compiler knows the type of <\/span><span>x * y<\/span><span>, that information is unavailable to you here.&nbsp; The C++0x keyword <\/span><span>decltype<\/span><span> removes this blind spot, allowing you to say &#8220;<\/span><span>multiply()<\/span><span> returns the type of <\/span><span>x * y<\/span><span>&#8220;.&nbsp; (<\/span><span>decltype<\/span><span> is an abbreviation of &#8220;declared type&#8221;; I pronounce it as rhyming with &#8220;speckle type&#8221;.)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><b><span>decltype: the pattern<\/p>\n<p><\/span><\/b><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>Here&#8217;s how to write a completely generic functor that wraps <\/span><span>operator+()<\/span><span>.&nbsp; This <\/span><span>Plus<\/span><span> functor is not a template, but it has a templated function call operator that takes two arguments of arbitrary (and possibly different) types, adds them together, and returns the result, which can be of arbitrary (and possibly different from both of the arguments) type.<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>C:Temp&gt;type plus.cpp<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>#include &lt;algorithm&gt;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>#include &lt;iostream&gt;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>#include &lt;iterator&gt;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>#include &lt;ostream&gt;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>#include &lt;s\ntring&gt;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>#include &lt;utility&gt;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>#include &lt;vector&gt;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>using namespace std;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>struct Plus {<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; template &lt;typename T, typename U&gt;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; <b>auto<\/b> operator()(T&amp;&amp; t, U&amp;&amp; u) const<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; <b>-&gt; decltype(forward&lt;T&gt;(t) + forward&lt;U&gt;(u))<\/b> {<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return forward&lt;T&gt;(t) + forward&lt;U&gt;(u);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; }<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>};<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>int main() {<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; vector&lt;int&gt; i;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; i.push_back(1);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; i.push_back(2);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; i.push_back(3);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; vector&lt;int&gt; j;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; j.push_back(40);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; j.push_back(50);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; j.push_back(60);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; vector&lt;int&gt; k;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; vector&lt;string&gt; s;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; s.push_back(&#8220;cut&#8221;);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; s.push_back(&#8220;flu&#8221;);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; s.push_back(&#8220;kit&#8221;);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; vector&lt;string&gt; t;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; t.push_back(&#8220;e&#8221;);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; t.push_back(&#8220;ffy&#8221;);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; t.push_back(&#8220;tens&#8221;);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; vector&lt;string&gt; u;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; transform(i.begin(), i.end(), j.begin(), back_inserter(k), Plus());<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; transform(s.begin(), s.end(), t.begin(), back_inserter(u), Plus());<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; for_each(k.begin(), k.end(), [](int n) { cout &lt;&lt; n &lt;&lt; &#8221; &#8220;; });<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; cout &lt;&lt; endl;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; for_each(u.begin(), u.end(), [](const string&amp; r) { cout &lt;&lt; r &lt;&lt; &#8221; &#8220;; });<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; cout &lt;&lt; endl;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>}<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>C:Temp&gt;cl \/EHsc \/nologo \/W4 plus.cpp<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>plus.cpp<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>C:Temp&gt;plus<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>41 52 63<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>cute fluffy kittens<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>Compare this to C++98\/03 &lt;functional&gt;&#8217;s <\/span><span>std::plus&lt;T&gt;<\/span><span> (which is unchanged in C++0x).&nbsp; Because it&#8217;s a class template, you&#8217;d have to pass <\/span><span>plus&lt;int&gt;()<\/span><span> and <\/span><span>plus&lt;string&gt;()<\/span><span>, repeating the element types.&nbsp; Its non-templated function call operator has the form <\/span><span>T operator()(const T&amp; x, const T&amp; y) const<\/span><span>, making it unable to deal with 2 different types, much less 3 different types, without resorting to implicit conversions.&nbsp; (You can feed <\/span><span>plus&lt;string&gt;()<\/span><span> a <\/span><span>string<\/span><span> and a <\/span><span>const char *<\/span><span>.&nbsp; That will construct a temporary <\/span><span>string<\/span><span> from the second argument, before concatenating the two <\/span><span>string<\/span><span>s.&nbsp; The performance of this is not especially desirable.)&nbsp; Finally, because it takes <\/span><span>const T&amp;<\/span><span>, it can&#8217;t take advantage of C++0x move semantics.&nbsp; <\/span><span>Plus<\/span><span> avoids all of this: <\/span><span>Plus()<\/span><span> doesn&#8217;t repeat the element type, it deals with the &#8220;3 different types&#8221; case, and because it uses perfect forwarding, it respects move semantics.<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><b><span>trailing return types<\/p>\n<p><\/span><\/b><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>Now, let&#8217;s look at that templated function call operator again:<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>template &lt;typename T, typename U&gt;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><b><span>auto<\/span><\/b><span> operator()(T&amp;&amp; t, U&amp;&amp; u) const<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><b><span>-&gt; decltype(forward&lt;T&gt;(t) + forward&lt;U&gt;(u))<\/span><\/b><span> {<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; return forward&lt;T&gt;(t) + forward&lt;U&gt;(u);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>}<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>Here, <\/span><span>auto<\/span><span> has a different meaning from <\/span><span>for (auto i = v.begin(); i != v.end(); ++i)<\/span><span>, where it says &#8220;make the type of this thing the same as the type of whatever initializes it&#8221;.&nbsp; When used as a return type, <\/span><span>auto<\/span><span> says &#8220;this function has a <i>trailing-return-type<\/i>; after I declare its parameters, I&#8217;ll tell you what its return type is&#8221;.&nbsp; (The C++0x Working Draft <a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2009\/n2857.pdf\"><font color=\"#0000ff\">N2857<\/font><\/a> calls this a <i>late-specified return type<\/i>, but this is being renamed to <i>trailing-return-type<\/i>; see paper <a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2009\/n2859.pdf\"><font color=\"#0000ff\">N2859<\/font><\/a>.)&nbsp; If this seems suspiciously similar to how lambdas are given explicit return types, that&#8217;s because it is.&nbsp; A lambda&#8217;s return type has to go on the right in order for its <i>lambda-introducer<\/i> <\/span><span>[]<\/span><span> to appear first.&nbsp; Here, the <\/span><span>decltype<\/span><span>-powered return type has to go on the right in order for the function parameters <\/span><span>t<\/span><span> and <\/span><span>u<\/span><span> to be declared first.&nbsp; Where the <\/span><span>auto<\/span><span> appears on the left, the template parameters <\/span><span>T<\/span><span> and <\/span><span>U<\/span><span> are visible, but the function parameters <\/span><span>t<\/span><span> and <\/span><span>u<\/span><span> are not yet visible, and that&#8217;s what <\/span><span>decltype<\/span><span> needs.&nbsp; (Technically, <\/span><span>decltype(forward&lt;T&gt;(*static_cast&lt;T *&gt;(0)) + forward&lt;U&gt;(*static_cast&lt;U *&gt;(0)))<\/span><span> could go on the left, but that&#8217;s an abomina\ntion.)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>As for the expression given to <\/span><span>decltype<\/span><span>, giving it the same expression as the <\/span><span>return<\/span><span> statement ensures correctness in all cases.&nbsp; (Pop quiz: why would <\/span><span>decltype(t + u)<\/span><span> be wrong?)&nbsp; The repetition here is unavoidable but centralized &#8211; it appears exactly once, on adjacent lines, so it is not dangerous.<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><b><span>another example<\/p>\n<p><\/span><\/b><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>For completeness, here&#8217;s that &#8220;3 different types&#8221; example:<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>C:Temp&gt;type mult.cpp<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>#include &lt;algorithm&gt;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>#include &lt;iostream&gt;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>#include &lt;iterator&gt;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>#include &lt;ostream&gt;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>#include &lt;utility&gt;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>#include &lt;vector&gt;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>using namespace std;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>struct Multiplies {<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; template &lt;typename T, typename U&gt;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; auto operator()(T&amp;&amp; t, U&amp;&amp; u) const<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; -&gt; decltype(forward&lt;T&gt;(t) * forward&lt;U&gt;(u)) {<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return forward&lt;T&gt;(t) * forward&lt;U&gt;(u);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; }<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>};<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>class Watts {<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>public:<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; explicit Watts(const int n) : m_n(n) { }<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; int get() const { return m_n; }<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>private:<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; int m_n;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>};<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>class Seconds {<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>public:<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; explicit Seconds(const int n) : m_n(n) { }<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; int get() const { return m_n; }<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>private:<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; int m_n;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>};<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>class Joules {<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>public:<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; explicit Joules(const int n) : m_<\/span><\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Part 1 of this series covered lambdas, auto, and static_assert. &nbsp; Part 2 of this series covered rvalue references, which enable move semantics and perfect forwarding. &nbsp; Today, I&#8217;m going to talk about decltype, which allows perfect forwarding functions to have arbitrary return types.&nbsp; It&#8217;s of interest to people who are writing highly generic code. [&hellip;]<\/p>\n","protected":false},"author":289,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4523","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cplusplus"],"acf":[],"blog_post_summary":"<p>Part 1 of this series covered lambdas, auto, and static_assert. &nbsp; Part 2 of this series covered rvalue references, which enable move semantics and perfect forwarding. &nbsp; Today, I&#8217;m going to talk about decltype, which allows perfect forwarding functions to have arbitrary return types.&nbsp; It&#8217;s of interest to people who are writing highly generic code. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/4523","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/289"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=4523"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/4523\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=4523"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=4523"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=4523"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}