blob: d29af9d56393b4a702b7ab7be86bc74d621e47e3 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Apache Mesos - C++ Style Guide</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta property="og:locale" content="en_US"/>
<meta property="og:type" content="website"/>
<meta property="og:title" content="Apache Mesos"/>
<meta property="og:site_name" content="Apache Mesos"/>
<meta property="og:url" content="http://mesos.apache.org/"/>
<meta property="og:image" content="http://mesos.apache.org/assets/img/mesos_logo_fb_preview.png"/>
<meta property="og:description"
content="Apache Mesos abstracts resources away from machines,
enabling fault-tolerant and elastic distributed systems
to easily be built and run effectively."/>
<meta name="twitter:card" content="summary"/>
<meta name="twitter:site" content="@ApacheMesos"/>
<meta name="twitter:title" content="Apache Mesos"/>
<meta name="twitter:image" content="http://mesos.apache.org/assets/img/mesos_logo_fb_preview.png"/>
<meta name="twitter:description"
content="Apache Mesos abstracts resources away from machines,
enabling fault-tolerant and elastic distributed systems
to easily be built and run effectively."/>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<link rel="alternate" type="application/atom+xml" title="Apache Mesos Blog" href="/blog/feed.xml">
<link href="../../assets/css/main.css" media="screen" rel="stylesheet" type="text/css" />
<!-- Google Analytics Magic -->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-20226872-1']);
_gaq.push(['_setDomainName', 'apache.org']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<!-- magical breadcrumbs -->
<div class="topnav">
<div class="container">
<ul class="breadcrumb">
<li>
<div class="dropdown">
<a data-toggle="dropdown" href="#">Apache Software Foundation <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<li><a href="http://www.apache.org">Apache Homepage</a></li>
<li><a href="http://www.apache.org/licenses/">License</a></li>
<li><a href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
<li><a href="http://www.apache.org/foundation/thanks.html">Thanks</a></li>
<li><a href="http://www.apache.org/security/">Security</a></li>
</ul>
</div>
</li>
<li><a href="http://mesos.apache.org">Apache Mesos</a></li>
<li><a href="/documentation
/">Documentation
</a></li>
</ul><!-- /.breadcrumb -->
</div><!-- /.container -->
</div><!-- /.topnav -->
<!-- navbar excitement -->
<div class="navbar navbar-default navbar-static-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#mesos-menu" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/"><img src="/assets/img/mesos_logo.png" alt="Apache Mesos logo"/></a>
</div><!-- /.navbar-header -->
<div class="navbar-collapse collapse" id="mesos-menu">
<ul class="nav navbar-nav navbar-right">
<li><a href="/gettingstarted/">Getting Started</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/documentation/latest/">Documentation</a></li>
<li><a href="/downloads/">Downloads</a></li>
<li><a href="/community/">Community</a></li>
</ul>
</div><!-- /#mesos-menu -->
</div><!-- /.container -->
</div><!-- /.navbar -->
<div class="content">
<div class="container">
<div class="row-fluid">
<div class="col-md-4">
<h4>If you're new to Mesos</h4>
<p>See the <a href="/gettingstarted/">getting started</a> page for more
information about downloading, building, and deploying Mesos.</p>
<h4>If you'd like to get involved or you're looking for support</h4>
<p>See our <a href="/community/">community</a> page for more details.</p>
</div>
<div class="col-md-8">
<h1>Mesos C++ Style Guide</h1>
<p>The Mesos codebase follows the <a href="https://google.github.io/styleguide/cppguide.html">Google C++ Style Guide</a> with some notable differences, as described below. Note that the <a href="/documentation/latest/./clang-format/">clang-format</a> tool can be helpful to ensure that some of the mechanical style rules are obeyed.</p>
<h2>Scoping</h2>
<h3>Namespaces</h3>
<ul>
<li>We avoid <code>using namespace foo</code> statements as it is not explicit about which symbols are pulled in, and it can often pull in a lot of symbols, which sometimes lead to conflicts.</li>
<li>It is OK to use namespace aliases to help pull in sub-namespaces, such as <code>namespace http = process::http;</code>. These should only be present at the top of the .cpp file.</li>
</ul>
<h2>Naming</h2>
<h3>Variable Names</h3>
<ul>
<li>We use <a href="https://en.wikipedia.org/wiki/Camel_case">lowerCamelCase</a> for variable names in Mesos application code (Google uses snake_case, and their class member variables have trailing underscores).</li>
<li>We use <a href="https://en.wikipedia.org/wiki/Snake_case">snake_case</a> for variable names in the libprocess and stout libraries.</li>
<li>We prepend constructor and function arguments with a leading underscore to avoid ambiguity and / or shadowing:</li>
</ul>
<pre><code class="{.cpp}">Try(State _state, T* _t = nullptr, const std::string&amp; _message = "")
: state(_state), t(_t), message(_message) {}
</code></pre>
<ul>
<li><p>Prefer trailing underscores for use as member fields (but not required). Some trailing underscores are used to distinguish between similar variables in the same scope (think prime symbols), <em>but this should be avoided as much as possible, including removing existing instances in the code base.</em></p></li>
<li><p>If you find yourself creating a copy of an argument passed by const reference, consider passing it by value instead (if you don&rsquo;t want to use a leading underscore and copy in the body of the function):</p></li>
</ul>
<pre><code class="{.cpp}">// You can pass-by-value in ProtobufProcess::install() handlers.
void Slave::statusUpdate(StatusUpdate update, const UPID&amp; pid)
{
...
update.mutable_status()-&gt;set_source(
pid == UPID() ? TaskStatus::SOURCE_SLAVE : TaskStatus::SOURCE_EXECUTOR);
...
}
</code></pre>
<h3>Constant Names</h3>
<ul>
<li>We use <a href="http://en.wikipedia.org/wiki/Letter_case#Special_case_styles">SCREAMING_SNAKE_CASE</a> for constant names in Mesos, libprocess, and stout (Google uses a <code>k</code> followed by mixed case, e.g. <code>kDaysInAWeek</code>).</li>
</ul>
<h3>Function Names</h3>
<ul>
<li>We use <a href="https://en.wikipedia.org/wiki/Camel_case">lowerCamelCase</a> for function names in Mesos application code (Google uses mixed case for regular functions; and their accessors and mutators match the name of the variable).</li>
<li>We use <a href="https://en.wikipedia.org/wiki/Snake_case">snake_case</a> for function names in the libprocess and stout libraries.</li>
</ul>
<h3>Class Names</h3>
<ul>
<li>We use <a href="https://en.wikipedia.org/wiki/Camel_case">UpperCamelCase</a> for class and struct names in Mesos, libprocess, and stout.</li>
</ul>
<h2>Strings</h2>
<ul>
<li>Strings used in log and error messages should end without a period.</li>
</ul>
<h2>Comments</h2>
<ul>
<li>End each sentence within a comment with a punctuation mark (please note that we generally prefer periods); this applies to incomplete sentences as well.</li>
<li>For trailing comments, leave one space.</li>
<li>Use backticks when quoting code excerpts or object/variable/function names. For example:</li>
</ul>
<pre><code class="{.cpp}">// Use `SchedulerDriver::acceptOffers()` to send several offer
// operations. This makes use of the `RESERVE()` and `UNRESERVE()`
// helpers, which take a `Resources` object as input and produce
// appropriate offer operations. Note that we are unreserving the
// resources contained in `dynamicallyReserved1`.
driver.acceptOffers({offer.id()},
{UNRESERVE(dynamicallyReserved1),
RESERVE(dynamicallyReserved2),
RESERVE(dynamicallyReserved3)},
filters);
</code></pre>
<h2>Breaks</h2>
<ul>
<li>Break before braces on enum, function, and record (i.e. struct, class, union) definitions.</li>
</ul>
<h2>Indentation</h2>
<h3>Class Format</h3>
<ul>
<li>Access modifiers are not indented (Google uses one space indentation).</li>
<li>Constructor initializers are indented by two spaces (Google indents by four).</li>
</ul>
<h3>Templates</h3>
<ul>
<li>Leave one space after the <code>template</code> keyword, e.g. <code>template &lt;typename T&gt;</code> rather than <code>template&lt;typename T&gt;</code>.</li>
</ul>
<h3>Function Definition/Invocation</h3>
<ul>
<li>Newline when calling or defining a function: indent with four spaces.</li>
<li>We do not follow Google&rsquo;s style of wrapping on the open parenthesis, the general goal is to reduce visual &ldquo;jaggedness&rdquo; in the code. Prefer (1), (4), (5), sometimes (3), never (2):</li>
</ul>
<pre><code class="{.cpp}">// 1: OK.
allocator-&gt;resourcesRecovered(frameworkId, agentId, resources, filters);
// 2: Don't use.
allocator-&gt;resourcesRecovered(frameworkId, agentId,
resources, filters);
// 3: Don't use in this case due to "jaggedness".
allocator-&gt;resourcesRecovered(frameworkId,
agentId,
resources,
filters);
// 3: In this case, 3 is OK.
foobar(someArgument,
someOtherArgument,
theLastArgument);
// 4: OK.
allocator-&gt;resourcesRecovered(
frameworkId,
agentId,
resources,
filters);
// 5: OK.
allocator-&gt;resourcesRecovered(
frameworkId, agentId, resources, filters);
</code></pre>
<h3>Continuation</h3>
<ul>
<li>Newline for an assignment statement: indent with two spaces.</li>
</ul>
<pre><code class="{.cpp}">Try&lt;Duration&gt; failoverTimeout =
Duration::create(FrameworkInfo().failover_timeout());
</code></pre>
<h2>Empty Lines</h2>
<ul>
<li>One empty line at the end of the file.</li>
<li>Inside a code block, every multi-line statement should be followed by one empty line.</li>
</ul>
<pre><code class="{.cpp}">Try&lt;very_very_long_type&gt; long_name =
::protobuf::parse&lt;very_very_long_type&gt;(
request);
for (int i = 0; i &lt; very_very_long_expression();
i++) {
// No empty line here for control constructs.
}
</code></pre>
<ul>
<li>Elements outside classes (classes, structs, global functions, etc.) should be spaced apart by two empty lines.</li>
<li>Elements inside classes (member variables and functions) should not be spaced apart by more than one empty line.</li>
</ul>
<h2>Capture by Reference</h2>
<p>We disallow capturing <strong>temporaries</strong> by reference. See <a href="https://issues.apache.org/jira/browse/MESOS-2629">MESOS-2629</a> for the rationale.</p>
<pre><code class="{.cpp}">Future&lt;Nothing&gt; f() { return Nothing(); }
Future&lt;bool&gt; g() { return false; }
struct T
{
T(const char* data) : data(data) {}
const T&amp; member() const { return *this; }
const char* data;
};
// 1: Don't use.
const Future&lt;Nothing&gt;&amp; future = f();
// 1: Instead use.
const Future&lt;Nothing&gt; future = f();
// 2: Don't use.
const Future&lt;Nothing&gt;&amp; future = Future&lt;Nothing&gt;(Nothing());
// 2: Instead use.
const Future&lt;Nothing&gt; future = Future&lt;Nothing&gt;(Nothing());
// 3: Don't use.
const Future&lt;bool&gt;&amp; future = f().then(lambda::bind(g));
// 3: Instead use.
const Future&lt;bool&gt; future = f().then(lambda::bind(g));
// 4: Don't use (since the T that got constructed is a temporary!).
const T&amp; t = T("Hello").member();
// 4: Preferred alias pattern (see below).
const T t("Hello");
const T&amp; t_ = t.member();
// 4: Can also use.
const T t = T("Hello").member();
</code></pre>
<p>We allow capturing non-temporaries by <em>constant reference</em> when the intent is to <strong>alias</strong>.</p>
<p>The goal is to make code more concise and improve readability. Use this if an expression referencing a field by <code>const</code> is:</p>
<ul>
<li>Used repeatedly.</li>
<li>Would benefit from a concise name to provide context for readability.</li>
<li>Will <strong>not</strong> be invalidated during the lifetime of the alias. Otherwise document this explicitly.</li>
</ul>
<pre><code class="{.cpp}">hashmap&lt;string, hashset&lt;int&gt;&gt; index;
// 1: Ok.
const hashset&lt;int&gt;&amp; values = index[2];
// 2: Ok.
for (auto iterator = index.begin(); iterator != index.end(); ++iterator) {
const hashset&lt;int&gt;&amp; values = iterator-&gt;second;
}
// 3: Ok.
foreachpair (const string&amp; key, const hashset&lt;int&gt;&amp; values, index) {}
foreachvalue (const hashset&lt;int&gt;&amp; values, index) {}
foreachkey (const string&amp; key, index) {}
// 4: Avoid aliases in most circumstances as they can be dangerous.
// This is an example of a dangling alias!
vector&lt;string&gt; strings{"hello"};
string&amp; s = strings[0];
strings.erase(strings.begin());
s += "world"; // THIS IS A DANGLING REFERENCE!
</code></pre>
<h2>File Headers</h2>
<ul>
<li><p>Mesos source files must contain the &ldquo;ASF&rdquo; header:</p>
<pre><code> // Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
</code></pre></li>
<li><p>Stout and libprocess source files must contain the &ldquo;Apache License Version 2.0&rdquo; header:</p>
<pre><code> // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License
</code></pre></li>
</ul>
<h2>Order of includes</h2>
<p>In addition to the ordering rules from the Google style guide, Mesos related headers are separated into sections. Newline to separate each section.
Mesos related headers in <code>include</code> directories are partitioned by their subfolders, sorted alphabetically, and included using brackets.
Header in <code>src</code> directories are included afterwards, using the same rules but with quotes instead of brackets.</p>
<p>Example for <code>src/common/foo.cpp</code>:</p>
<pre><code class="{.cpp}">#include "common/foo.hpp"
#include &lt;stdint.h&gt;
#include &lt;string&gt;
#include &lt;vector&gt;
#include &lt;boost/circular_buffer.hpp&gt;
#include &lt;mesos/mesos.hpp&gt;
#include &lt;mesos/type_utils.hpp&gt;
#include &lt;mesos/module/authenticator.hpp&gt;
#include &lt;mesos/scheduler/scheduler.hpp&gt;
#include &lt;process/http.hpp&gt;
#include &lt;process/protobuf.hpp&gt;
#include &lt;stout/foreach.hpp&gt;
#include &lt;stout/hashmap.hpp&gt;
#include "common/build.hpp"
#include "common/protobuf_utils.hpp"
#include "master/flags.hpp"
</code></pre>
<h2>C++11</h2>
<p>We support C++11 and require GCC 4.8+ or Clang 3.5+ compilers. The whitelist of supported C++11 features is:</p>
<ul>
<li><code>nullptr</code></li>
<li>Static assertions.</li>
<li>Multiple right angle brackets.</li>
<li>Type inference (<code>auto</code> and <code>decltype</code>). The main goal is to increase code readability. This is safely the case if the exact same type omitted on the left is already fully stated on the right. Here are several examples:</li>
</ul>
<pre><code class="{.cpp}">// 1: OK.
const auto i = values.find(keys.front());
// Compare with
const typename map::iterator i = values.find(keys.front());
// 2: OK.
auto names = shared_ptr&lt;list&lt;string&gt;&gt;(new list&lt;string&gt;());
// Compare with
shared_ptr&lt;list&lt;string&gt;&gt; names = shared_ptr&lt;list&lt;string&gt;&gt;(new list&lt;string&gt;());
// 3: Don't use.
auto authorizer = LocalAuthorizer::create(acls);
// Compare with
Try&lt;Owned&lt;LocalAuthorizer&gt;&gt; authorizer = LocalAuthorizer::create();
</code></pre>
<ul>
<li>Rvalue references.</li>
<li>Explicitly-defaulted functions.</li>
<li>Variadic templates.</li>
<li>Delegating constructors.</li>
<li>Mutexes.
<ul>
<li><code>std::mutex</code></li>
<li><code>std::lock_guard&lt;std::mutex&gt;</code></li>
<li><code>std::unique_lock&lt;std::mutex&gt;</code></li>
</ul>
</li>
<li>Atomics (<code>std::atomic</code>)
<ul>
<li>The standard defines a number of predefined typedefs for atomic types (e.g., <code>std::atomic_int</code>), in addition to <code>std::atomic&lt;T&gt;</code>. When a typedef is available, it should be preferred over explicit template specialization of <code>std::atomic&lt;T&gt;</code>.</li>
<li>When reading from and writing to atomic values, the <code>load</code> and <code>store</code> member functions should be used instead of the overloads of <code>operator T()</code> and <code>operator=</code>. Being explicit helps to draw the reader&rsquo;s attention to the fact that atomic values are being manipulated.</li>
</ul>
</li>
<li>Shared from this.
<ul>
<li><code>class T : public std::enable_shared_from_this&lt;T&gt;</code></li>
<li><code>shared_from_this()</code></li>
</ul>
</li>
<li>Lambdas!
<ul>
<li>Don&rsquo;t put a space between the capture list and the parameter list:</li>
</ul>
</li>
</ul>
<pre><code class="{.cpp}">// 1: OK.
[]() { ...; };
// 2: Don't use.
[] () { ...; };
</code></pre>
<ul>
<li>Prefer default capture by value, explicit capture by value, then capture by reference. To avoid dangling-pointer bugs, <em>never</em> use default capture by reference:</li>
</ul>
<pre><code class="{.cpp}">// 1: OK.
[=]() { ... }; // Default capture by value.
[n]() { ... }; // Explicit capture by value.
[&amp;n]() { ... }; // Explicit capture by reference.
[=, &amp;n]() { ... }; // Default capture by value, explicit capture by reference.
// 2: Don't use.
[&amp;]() { ... }; // Default capture by reference.
</code></pre>
<ul>
<li>Use <code>mutable</code> only when absolutely necessary.</li>
</ul>
<pre><code class="{.cpp}">// 1: OK.
[]() mutable { ...; };
</code></pre>
<ul>
<li>Feel free to ignore the return type by default, adding it as necessary to appease the compiler or be more explicit for the reader.</li>
</ul>
<pre><code class="{.cpp}">// 1: OK.
[]() { return true; };
[]() -&gt; bool { return ambiguous(); };
</code></pre>
<ul>
<li>Feel free to use <code>auto</code> when naming a lambda expression:</li>
</ul>
<pre><code class="{.cpp}">// 1: OK.
auto lambda = []() { ...; };
</code></pre>
<ul>
<li>Format lambdas similar to how we format functions and methods. Feel free to let lambdas be one-liners:</li>
</ul>
<pre><code class="{.cpp}">// 1: OK.
auto lambda = []() {
...;
};
// 2: OK.
auto lambda = []() { ...; };
</code></pre>
<ul>
<li>Feel free to inline lambdas within function arguments:</li>
</ul>
<pre><code class="{.cpp}">instance.method([]() {
...;
});
</code></pre>
<ul>
<li>Chain function calls on a newline after the closing brace of the lambda and the closing parenthesis of function call:</li>
</ul>
<pre><code class="{.cpp}">// 1: OK.
instance
.method([]() {
...;
})
.then([]() { ...; })
.then([]() {
...;
});
// 2: OK (when no chaining, compare to 1).
instance.method([]() {
...;
});
// 3: OK (if no 'instance.method').
function([]() {
...;
})
.then([]() { ...; })
.then([]() {
...;
});
// 3: OK (but prefer 1).
instance.method([]() {
...;
})
.then([]() { ...; })
.then([]() {
...;
});
</code></pre>
<ul>
<li>Wrap capture lists independently of parameters, <em>use the same formatting as if the capture list were template parameters</em>:</li>
</ul>
<pre><code class="{.cpp}">// 1: OK.
function([&amp;capture1, &amp;capture2, &amp;capture3](
const T1&amp; p1, const T2&amp; p2, const T3&amp; p3) {
...;
});
function(
[&amp;capture1, &amp;capture2, &amp;capture3](
const T1&amp; p1, const T2&amp; p2, const T3&amp; p3) {
...;
});
auto lambda = [&amp;capture1, &amp;capture2, &amp;capture3](
const T1&amp; p1, const T2&amp; p2, const T3&amp; p3) {
...;
};
auto lambda =
[&amp;capture1, &amp;capture2, &amp;capture3](
const T1&amp; p1, const T2&amp; p2, const T3&amp; p3) {
...;
};
// 2: OK (when capture list is longer than 80 characters).
function([
&amp;capture1,
&amp;capture2,
&amp;capture3,
&amp;capture4](
const T1&amp; p1, const T2&amp; p2) {
...;
});
auto lambda = [
&amp;capture1,
&amp;capture2,
&amp;capture3,
&amp;capture4](
const T1&amp; p1, const T2&amp; p2) {
...;
};
// 3: OK (but prefer 2).
function([
&amp;capture1,
&amp;capture2,
&amp;capture3,
&amp;capture4](const T1&amp; p1, const T2&amp; t2) {
...;
});
auto lambda = [
&amp;capture1,
&amp;capture2,
&amp;capture3,
&amp;capture4](const T1&amp; p1, const T2&amp; p2) {
...;
};
// 3: Don't use.
function([&amp;capture1,
&amp;capture2,
&amp;capture3,
&amp;capture4](const T1&amp; p1, const T2&amp; p2) {
...;
});
auto lambda = [&amp;capture1,
&amp;capture2,
&amp;capture3,
&amp;capture4](const T1&amp; p1, const T2&amp; p2) {
...;
};
// 4: Don't use.
function([&amp;capture1,
&amp;capture2,
&amp;capture3,
&amp;capture4](
const T1&amp; p1, const T2&amp; p2, const T3&amp; p3) {
...;
});
auto lambda = [&amp;capture1,
&amp;capture2,
&amp;capture3,
&amp;capture4](
const T1&amp; p1, const T2&amp; p2, const T3&amp; p3) {
...;
};
// 5: Don't use.
function([&amp;capture1,
&amp;capture2,
&amp;capture3,
&amp;capture4](
const T1&amp; p1,
const T2&amp; p2,
const T3&amp; p3) {
...;
});
auto lambda = [&amp;capture1,
&amp;capture2,
&amp;capture3,
&amp;capture4](
const T1&amp; p1,
const T2&amp; p2,
const T3&amp; p3) {
...;
};
// 6: OK (parameter list longer than 80 characters).
function([&amp;capture1, &amp;capture2, &amp;capture3](
const T1&amp; p1,
const T2&amp; p2,
const T3&amp; p3,
const T4&amp; p4) {
...;
});
auto lambda = [&amp;capture1, &amp;capture2, &amp;capture3](
const T1&amp; p1,
const T2&amp; p2,
const T3&amp; p3,
const T4&amp; p4) {
...;
};
// 7: OK (capture and parameter lists longer than 80 characters).
function([
&amp;capture1,
&amp;capture2,
&amp;capture3,
&amp;capture4](
const T1&amp; p1,
const T2&amp; p2,
const T3&amp; p3,
const T4&amp; p4) {
...;
});
auto lambda = [
&amp;capture1,
&amp;capture2,
&amp;capture3,
&amp;capture4](
const T1&amp; p1,
const T2&amp; p2,
const T3&amp; p3,
const T4&amp; p4) {
...;
};
</code></pre>
<ul>
<li><p>Unrestricted Union.</p>
<p>Like the pre-existing <code>union</code>, we can overlap storage allocation for objects that never exist simultaneously. However, with C++11 we are no longer <em>restricted to having only non-POD types in unions</em>. Adding non-POD types to unions complicates things, however, because we need to make sure to properly call constructors and destructors. Therefore, only use unrestricted unions (i.e., unions with non-POD types) when the union has only a single field. What does this buy us? Now we can avoid dynamic memory allocations for &ldquo;container&rdquo; like types, e.g., <code>Option</code>, <code>Try</code>, <code>Result</code>, etc. In effect, we treat the union like a dynamic allocation, calling <em>placement new</em>, <code>new (&amp;t) T(...)</code> anyplace we would have just called <code>new T(...)</code> and the destructor <code>t.~T()</code> anyplace we would have called <code>delete t</code>.</p></li>
<li><p>Constant expressions.</p>
<p>Constant expressions allow the declaration of static non-POD objects while eliminating the unpredictable runtime initialization and destruction issues normally encountered, helping eliminate macros and hard-coded literals without sacrificing performance and type safety. Changes which require converting from <code>constexpr</code> to <code>const</code> can propagate through the dependency tree requiring that dependent <code>constexpr</code> uses also be converted to <code>const</code>, hence we avoid using <code>constexpr</code> in complex functions.</p>
<p><code>constexpr</code> behaves as a combination of <code>inline</code> and <code>const</code> and hence must be defined before use in another <code>constexpr</code>.</p>
<p>Prefer <code>constexpr</code> to <code>const</code> for all constant POD declarations, <code>constexpr</code> <code>char</code> arrays are preferred to <code>const</code> <code>string</code> literals.</p></li>
</ul>
<pre><code class="{.cpp}"> // OK
constexpr char LITERAL[] = "value";
// Not OK - not available at compile time for optimization and
// definition required in a separate compilation module.
const char LITERAL[];
// Not OK - uncertain initialization order, cannot be used in other
// constexpr statements.
const string LITERAL("value");
</code></pre>
<p> <code>constexpr</code> functions are evaluated at compile time if all their arguments are constant expressions. Otherwise they default to initialization at runtime. However <code>constexpr</code> functions are limited in that they cannot perform dynamic casts, memory allocation or calls to non-constexpr functions. Prefer <code>constexpr</code> over const inline functions.</p>
<pre><code class="{.cpp}"> constexpr size_t MIN = 200;
constexpr size_t MAX = 1000;
constexpr size_t SPAN() { return MAX-MIN; }
int array[SPAN()];
</code></pre>
<p>Const expression constructors allow object initialization at compile time provided that all the constructor arguments are <code>constexpr</code> and the constructor body is empty, i.e. all initialization is performed in the initialization list. Classes which provide <code>constexpr</code> constructors should normally also provide <code>constexpr</code> copy constructors to allow the class to be used in the return value from a <code>constexpr</code> function.</p>
<pre><code class="{.cpp}"> class C
{
public:
constexpr C(int _i) : i(_i) {};
constexpr C(const C&amp; c) : i(c.i) {}
private:
const int i;
};
</code></pre>
<p> C++11 does not provide <code>constexpr string</code> or <code>constexpr</code> containers in the STL and hence <code>constexpr</code> cannot be used for any class using stout&rsquo;s Error() class.</p>
</div>
</div>
</div><!-- /.container -->
</div><!-- /.content -->
<hr>
<!-- footer -->
<div class="footer">
<div class="container">
<div class="col-md-4 social-blk">
<span class="social">
<a href="https://twitter.com/ApacheMesos"
class="twitter-follow-button"
data-show-count="false" data-size="large">Follow @ApacheMesos</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
<a href="https://twitter.com/intent/tweet?button_hashtag=mesos"
class="twitter-hashtag-button"
data-size="large"
data-related="ApacheMesos">Tweet #mesos</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
</span>
</div>
<div class="col-md-8 trademark">
<p>&copy; 2012-2017 <a href="http://apache.org">The Apache Software Foundation</a>.
Apache Mesos, the Apache feather logo, and the Apache Mesos project logo are trademarks of The Apache Software Foundation.
<p>
</div>
</div><!-- /.container -->
</div><!-- /.footer -->
<!-- JS -->
<script src="//code.jquery.com/jquery-1.11.0.min.js" type="text/javascript"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js" type="text/javascript"></script>
</body>
</html>