Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<blockquote> <p>I'd like to write a template function</p> <pre><code>template &lt;typename T&gt; void f( T v ); </code></pre> <p>such that <code>v</code> will be passed by value if it's small enough, otherwise by reference-to-const.</p> </blockquote> <p><strong>The compiler can be smart enough to do the right thing without any template magic,</strong> especially if the function <code>f</code> can be inlined. I would always implement <code>f</code> as </p> <pre><code>template &lt;typename T&gt; void f(const T&amp; v); </code></pre> <p>and trust the compiler to turn that into a copy if the copy is cheaper.</p> <p>Here is an example:</p> <pre><code>extern volatile int k; extern volatile int m; static void f(const int&amp; j) noexcept { // or f(const int j) for (int i=0; i&lt;j; ++i) { m = i; } } void g() noexcept { int j = k; f(j); } </code></pre> <p>I ran <code>clang++ -O3 -std=c++11 -S -emit-llvm filename.cpp</code> and the generated assembly (as far as I can tell) is the same.</p> <p>Pass by reference:</p> <pre><code>@k = external global i32 @m = external global i32 ; Function Attrs: nounwind uwtable define void @_Z1gv() #0 { entry: %0 = load volatile i32* @k, align 4, !tbaa !0 %cmp3.i = icmp sgt i32 %0, 0 br i1 %cmp3.i, label %for.body.i, label %_ZL1fRKi.exit for.body.i: ; preds = %entry, %for.body.i %i.04.i = phi i32 [ %inc.i, %for.body.i ], [ 0, %entry ] store volatile i32 %i.04.i, i32* @m, align 4, !tbaa !0 %inc.i = add nsw i32 %i.04.i, 1 %exitcond = icmp eq i32 %inc.i, %0 br i1 %exitcond, label %_ZL1fRKi.exit, label %for.body.i _ZL1fRKi.exit: ; preds = %for.body.i, %entry ret void } </code></pre> <p>Pass by value:</p> <pre><code>@k = external global i32 @m = external global i32 ; Function Attrs: nounwind uwtable define void @_Z1gv() #0 { entry: %0 = load volatile i32* @k, align 4, !tbaa !0 %cmp3.i = icmp sgt i32 %0, 0 br i1 %cmp3.i, label %for.body.i, label %_ZL1fi.exit for.body.i: ; preds = %entry, %for.body.i %i.04.i = phi i32 [ %inc.i, %for.body.i ], [ 0, %entry ] store volatile i32 %i.04.i, i32* @m, align 4, !tbaa !0 %inc.i = add nsw i32 %i.04.i, 1 %exitcond.i = icmp eq i32 %inc.i, %0 br i1 %exitcond.i, label %_ZL1fi.exit, label %for.body.i _ZL1fi.exit: ; preds = %for.body.i, %entry ret void } </code></pre> <p>If <code>f</code> is not inlined then the assembly is different though.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload