title: Why does boost::call_traits pass small objects like pair<char, char> by reference?
body: <p>I need a way to decide whether to pass an arbitrary type T by copy or by const-reference (e.g., if T is small enough then copy if, otherwise pass it by const-reference). To avoid reinventing the wheel, I tried out Boost Call Traits.</p>
  
  <p>As expected, primitive types are passed by value, and complex types like <code>std::string</code> are passed by reference. However, tiny non-primitive types are also passed by reference, e.g., <code>std::pair&lt;char, char&gt;</code>, which does not seem to be the best choice. I assumed that everything up to <code>sizeof(void*)</code> would be passed by value.</p>
  
  <p>Generally, the Boost libraries are of high quality, so maybe I am missing something.</p>
  
  <p>Here is my test code:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;type_traits&gt;
  #include &lt;tuple&gt;
  #include &lt;boost/call_traits.hpp&gt;
  
  template &lt;typename TYPE&gt;
  void test(const char* type_name)
  {
    typedef typename boost::call_traits&lt;TYPE&gt;::param_type T;  
    if(std::is_reference&lt;T&gt;::value)        
      std::cout &lt;&lt; type_name &lt;&lt; " is passed by reference (sizeof=" &lt;&lt; sizeof(TYPE) &lt;&lt; ")\n"; 
    else 
      std::cout &lt;&lt; type_name &lt;&lt; " is passed by value (sizeof=" &lt;&lt; sizeof(TYPE) &lt;&lt; ")\n"; 
  }
  
  int main()
  {
    test&lt;short&gt;("short");
    test&lt;int&gt;("int");
    test&lt;double&gt;("double");
    test&lt;std::string&gt;("std::string");
    test&lt;long long&gt;("long long");
    test&lt;std::pair&lt;int, int&gt;&gt;("std::pair&lt;int, int&gt;");
    test&lt;std::pair&lt;short, short&gt;&gt;("std::pair&lt;short, short&gt;");
    test&lt;std::pair&lt;char, char&gt;&gt;("std::pair&lt;char, char&gt;");
    test&lt;std::tuple&lt;char, char&gt;&gt;("std::tuple&lt;char, char&gt;");
    test&lt;std::tuple&lt;char, char, char, char&gt;&gt;("std::tuple&lt;char, char, char, char&gt;");
    test&lt;std::pair&lt;long long, long long&gt;&gt;("std::pair&lt;long long, long long&gt;");
    return 0;
  }
  </code></pre>
  
  <p>And here are the results (Boost 1.50, g++ 4.7.2):</p>
  
  <pre><code>short is passed by value (sizeof=2)
  int is passed by value (sizeof=4)
  double is passed by value (sizeof=8)
  std::string is passed by reference (sizeof=8)
  long long is passed by value (sizeof=8)
  std::pair&lt;int, int&gt; is passed by reference (sizeof=8)
  std::pair&lt;short, short&gt; is passed by reference (sizeof=4)
  std::pair&lt;char, char&gt; is passed by reference (sizeof=2)
  std::tuple&lt;char, char&gt; is passed by reference (sizeof=2)
  std::tuple&lt;char, char, char, char&gt; is passed by reference (sizeof=4)
  std::pair&lt;long long, long long&gt; is passed by reference (sizeof=16)
  </code></pre>