Automatic Evaluation Strategy Selection in C++
Consider the following function template:
template<typename T> void Foo(T)
{
  // ...
}
Pass-by-value semantics make sense if T happens to be an integral type, or at least a type that's cheap to copy.
Using pass-by-[const]-reference semantics, on the other hand, makes more sense if T happens to be an expensive type to copy.
Let's assume for a second that you are writing a library. Ideally, as a library implementer, your job is to provide your consumers with a clean API that is both as generic and efficient as possible. How then, do you provide a generic interface that caters to both types of argument passing strategies?
Here is my first attempt at getting this to work:
#include <boost/type_traits.hpp>
template<typename T> struct DefaultCondition
{
  enum {value = boost::is_integral<T>::value /* && <other trait(s)> */};
};
template< typename T, class Condition = DefaultCondition<T> > class Select
{
  template<bool PassByValue = Condition::value, class Dummy = void> struct Resolve
  {
    typedef T type;
  };
  template<class Dummy> struct Resolve<false, Dummy>
  {
    typedef const T& type;
  };
  public: typedef typename Resolve<>::type type;
};
Typical usage:
template<typename T> class EnterpriseyObject
{
  typedef typename Select<T>::type type;
  public: explicit EnterpriseyObject(type)
  {
    // ...
  }
};
struct CustomType {};
void Usage()
{
  EnterpriseyObject<int>(0); // Pass-by-value.
  (EnterpriseyObject<CustomType>(CustomType())); // Pass-by-const-reference.
}
This, of course, indirectly breaks implicit template argument deduction for non-class templates:
template<typename T> void Foo(typename Select<T>::type)
{
  // ...
}
void Usage()
{
  Foo(0);      // Incomplete.
  Foo<int>(0); // Fine.
}
This can be "fixed" with the Boost.Typeof library and a macro, a la the WinAPI:
#define Foo(Arg) ::Foo<BOOST_TYPEOF((Arg))>((Arg))
Though this is just a quasi-portable hack.
As you can see, my general approach is not really satisfactory for all cases.
As a hobbyist programmer, I neither have real-world experience nor do I have access to production-quality code for reference. I also realize that this might seem like a bad case of premature optimization, but I'm genuinely interested in a couple of things:
- Do you, or have you used this type of optimization* in the past?
- Does the Boost(or any other public) library already provide similar functio开发者_开发问答nality?
- If the answer to #1 or #2 is a 'yes' -- how is the non-class template case handled?
- Are there any obvious pitfalls that I'm not seeing with something like this?
- Finally, is this even a sane thing to do?
* Not profiled. ;)
- Yes. All the time. I use it myself.
- Yes, use Boost.Utility's Call Traits :) - Usage would be... - template <typename T> void foo(boost::call_traits<T>::param_type param) { // Use param }
- As far as I know, non-class templates are passed-by-value unless it is faster to not. Thanks to partial template specialization, it can be customized relatively easily. 
- Sorry, didn't really read what you did, it just looked like exactly what I went through a few months ago. Therefore, can't really answer this one. My recommendation is just to read through Boost.Utility. 
- Of course! 
 
         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论