Skip to content

Commit b6a80e5

Browse files
committed
Add some recent clarifications
The advice on function inlining now calls out explicit template instantiation. The advice on TODOs now shows an example of CLion's unique style.
1 parent 32019d0 commit b6a80e5

File tree

1 file changed

+90
-3
lines changed

1 file changed

+90
-3
lines changed

cppguide.html

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,20 @@ <h3 id="Inline_Functions">Inline Functions</h3>
397397
<div class="definition">
398398
<p>You can declare functions in a way that allows the compiler to expand
399399
them inline rather than calling them through the usual
400-
function call mechanism.</p>
400+
function call mechanism.
401+
<span class="drake">To achieve this, define the function in the header
402+
(<tt>*.h</tt>) file, instead of the <tt>*.cc</tt> file.</span>
403+
</p>
404+
405+
<p class="drake">Note that
406+
<a href="https://en.cppreference.com/w/cpp/language/class_template#Explicit_instantiation">
407+
explicit template instantiation</a> enables the use of templated classes or
408+
functions without defining them in the header file.</p>
409+
410+
<p class="drake">The C++ keyword <tt>inline</tt> is a separate concept
411+
related to linking, not function inlining. Some function definitions need
412+
to be marked with the <tt>inline</tt> keyword to avoid linking errors related
413+
to multiple definitions.</p>
401414
</div>
402415

403416
<div class="pros">
@@ -436,6 +449,71 @@ <h3 id="Inline_Functions">Inline Functions</h3>
436449
place its definition in the class, either for convenience
437450
or to document its behavior, e.g., for accessors and
438451
mutators.</p>
452+
453+
<p class="drake">The use of a numerical scalar class template is not a
454+
sufficient reason on its own to place a method definition in a header file.
455+
When a class is templated only on its numerical scalar type, Drake provides the
456+
<a href="https://drake.mit.edu/doxygen_cxx/group__default__scalars.html">
457+
default scalars</a> macros to declare and define the template instantiations
458+
that allow placing definitions into the <tt>*.cc</tt> file. These macros should
459+
be used whenever practical, and the class's method definitions should be placed
460+
into the <tt>*.cc</tt> file in most cases, consistent with the above rules of
461+
thumb.</p>
462+
463+
<p class="drake">Example header file:</p>
464+
465+
<pre class="drake">#include "drake/common/default_scalars.h"
466+
467+
namespace sample {
468+
469+
template &lt;typename T&gt;
470+
class MySystem final : public LeafSystem&lt;T&gt; {
471+
public:
472+
// Expensive functions such as this constructor or destructor are not inlined.
473+
MySystem();
474+
~MySystem() final;
475+
476+
// Short and inexpensive accessors can be inlined.
477+
int size() { return get_output_port(0).size(); }
478+
479+
private:
480+
// This calculation function is also expensive, and therefore isn't inlined.
481+
void CalcFoo(const Context&lt;T&gt;& context, BasicVector&lt;T&gt;* output);
482+
};
483+
484+
} // namespace sample
485+
486+
DRAKE_DECLARE_CLASS_TEMPLATE_INSTANTIATIONS_ON_DEFAULT_SCALARS(
487+
class ::sample::MySystem)
488+
</pre>
489+
490+
<p class="drake">Example cc file:</p>
491+
<pre class="drake">#include "my_system.h"
492+
493+
namespace sample {
494+
495+
// Even though the constructor appears to be short, by virtue of implicitly
496+
// calling the LeafSystem base class constructor it fails to meet the 10-line
497+
// rule of thumb.
498+
template &lt;typename T&gt;
499+
MySystem&lt;T&gt;::MySystem() = default;
500+
501+
// Ditto for the destructor.
502+
template &lt;typename T&gt;
503+
MySystem&lt;T&gt;::~MySystem() = default;
504+
505+
template &lt;typename T&gt;
506+
void MySystem&lt;T&gt;::CalcFoo(
507+
const Context&lt;T&gt;& context,
508+
BasicVector&lt;T&gt;* output) {
509+
// ... (10+ lines long, etc.) ...
510+
}
511+
512+
} // namespace sample
513+
514+
DRAKE_DEFINE_CLASS_TEMPLATE_INSTANTIATIONS_ON_DEFAULT_SCALARS(
515+
class ::sample::MySystem)
516+
</pre>
439517
</div>
440518

441519
</div>
@@ -2514,7 +2592,6 @@ <h3 id="General_Rules">General Rules</h3>
25142592
<li>Embrace templates/C++14 when it makes the code more correct (more clear
25152593
or more readable also implies more correct).</li>
25162594
<li>Minimize template requirements on public interfaces.</li>
2517-
<li>Avoid explicit template instantiations in cc files when possible.</li>
25182595
</ul>
25192596

25202597
</div>
@@ -5552,7 +5629,7 @@ <h3 id="TODO_Comments">TODO Comments</h3>
55525629
<div>
55535630
<pre>// TODO(kl@gmail.com): Use a "*" here for concatenation operator.
55545631
// TODO(Zeke) change this to use relations.
5555-
// TODO(bug 12345): remove the "Last visitors" feature
5632+
// TODO(#12345): remove the "Last visitors" feature
55565633
</pre>
55575634
</div>
55585635

@@ -5562,6 +5639,16 @@ <h3 id="TODO_Comments">TODO Comments</h3>
55625639
specific event ("Remove this code when all clients can
55635640
handle XML responses.").</p>
55645641

5642+
<p class="drake">For multi-line TODO comments, we allow a specific indentation
5643+
convention that is compatible with the CLion IDE's syntax highlighting:</p>
5644+
5645+
<pre class="drake">// TODO(#12345): This is a multi-line comment where after each line break we
5646+
// use one or more extra horizontal spaces so that the subsequent lines are
5647+
// understood by CLion to be a continuation of the first line.
5648+
</pre>
5649+
5650+
<p class="drake">This indentation is allowed, but not required. We mention it
5651+
here only for the avoidence of doubt during code reviews.</p>
55655652
</div>
55665653

55675654
<h3 id="Deprecation_Comments">Deprecation Comments</h3>

0 commit comments

Comments
 (0)