Note that there are some explanatory texts on larger screens.

plurals
  1. POShould all/most setter functions in C++11 be written as function templates accepting universal references?
    primarykey
    data
    text
    <p>Consider a class <code>X</code> with <code>N</code> member variables, each of some <em>copiable</em> and <em>movable</em> type, and <code>N</code> corresponding setter functions. In C++98, the definition of <code>X</code> would likely look something like this:</p> <pre><code>class X { public: void set_a(A const&amp; a) { _a = a; } void set_b(B const&amp; b) { _b = b; } ... private: A _a; B _b; ... }; </code></pre> <p>Setter functions of class <code>X</code> above can bind both to lvalue and to rvalue arguments. Depending on the actual argument, this <em>might</em> result in the creation of a temporary and <em>will</em> eventually result in a copy assignment; due to this, <em>non-copiable</em> types are not supported by this design.</p> <p>With C++11 we have move semantics, perfect forwarding, and universal references (Scott Meyers's terminology), which allow for a more efficient and generalized use of setter functions by rewriting them this way:</p> <pre><code>class X { public: template&lt;typename T&gt; void set_a(T&amp;&amp; a) { _a = std::forward&lt;T&gt;(a); } template&lt;typename T&gt; void set_b(T&amp;&amp; b) { _b = std::forward&lt;T&gt;(b); } ... private: A _a; B _b; ... }; </code></pre> <p>Universal references can bind to <code>const</code>/non-<code>const</code>, <code>volatile</code>/non-<code>volatile</code>, and to any convertible type in general, avoiding the creation of temporaries and passing values straight to <code>operator =</code>. <em>Non-copiable</em>, <em>movable</em> types are now supported. Possibly undesired bindings can be eliminated either through <code>static_assert</code> or through <code>std::enable_if</code>.</p> <p>So my question is: as a <em>design guideline</em>, should all (let's say, most) setter functions in C++11 be written as function templates accepting universal references?</p> <p>Apart from the more cumbersome syntax and the impossibility of using Intellisense-like helper tools when writing code in those setter functions, are there any relevant disadvantages with the hypothetical principle "<em>write setter functions as function templates accepting universal references whenever possible</em>"?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. COTo me, yes they should if you cannot pass by value. Also many constructors should be variadic and take universal references (`struct foo : bar { template <typename... Ts> foo (Ts&&... ts) : bar (std::forward<Ts> (ts)...) {} };`). Getters and setters are rare actually, so intellisense is not a big deal here.
      singulars
    2. CO@AlexandreC. that example seems like a bad one. Did you know that constructor will get picked over a regular copy constructor (i.e. declared as `foo(foo const&)`) for making copies (http://flamingdangerzone.com/cxx11/2012/06/05/is_related.html)? It doesn't forward initializer lists properly either. On the other hand, the language now has inherited ctors (compiler writers, could you pretty please with sugar on top implement these?), so you can get something much more robust than that ctor that with a simple `using bar::bar;`.
      singulars
    3. COWhy (on earth) is this thing not a public field? Especially if you wanted to be able to do anything with it that you could you do with a normal field. If you want a write-only property, make it a _method_ (a.o.t. a _setter_)
      singulars
 

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