C ++中的自动评估策略选择

时间:2010-07-07 04:08:08

标签: c++ templates pass-by-reference parameter-passing pass-by-value

考虑以下功能模板:

template<typename T> void Foo(T)
{
  // ...
}

如果T碰巧是一个整数类型,或者至少是一种复制成本低廉的类型,那么按值传递语义是有意义的。 另一方面,如果T恰好是要复制的昂贵类型,则使用pass-by- [const] -reference语义会更有意义。

让我们假设您正在编写一个库。理想情况下,作为库实现者,您的工作是为您的消费者提供尽可能通用且高效的干净API。那么,你是如何提供一个适合两种类型的参数传递策略的通用接口?


这是我第一次尝试这项工作:

#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;
};

典型用法:

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.
}

当然,这间接地打破了非类模板的隐式模板参数推导:

template<typename T> void Foo(typename Select<T>::type)
{
  // ...
}

void Usage()
{
  Foo(0);      // Incomplete.
  Foo<int>(0); // Fine.
}

这可以通过Boost.Typeof库和宏来修复,WinAPI

#define Foo(Arg) ::Foo<BOOST_TYPEOF((Arg))>((Arg))

虽然这只是一个准便携式黑客攻击。

正如您所看到的,我的一般方法对所有情况都不是很满意。


作为业余爱好者,我既没有实际经验,也没有生产质量代码供参考。我也意识到这似乎是过早优化的一个坏例子,但我真的对以下几点感兴趣:

  1. 你或者过去曾使用过这种类型的优化吗?
  2. Boost(或任何其他公共)库是否已提供类似的功能?
  3. 如果对#1或#2的回答是'是' - 非处理模板案例是如何处理的?
  4. 有没有明显的陷阱,我没有看到这样的事情?
  5. 最后,这甚至是理智的事情吗?

  6. *未分析。 ;)

1 个答案:

答案 0 :(得分:2)

  1. 是。每时每刻。我自己用它。
  2. 是的,请使用Boost.Utility's Call Traits:)

    用法是......

    template <typename T>
    void foo(boost::call_traits<T>::param_type param)
    {
        // Use param
    }
    
  3. 据我所知,非类模板是按值传递的,除非它更快。由于部分模板专业化,它可以相对容易地定制。

  4. 很抱歉,没有真正读过你所做的,它看起来就像我几个月前经历的那样。因此,无法真正回答这一点。我的建议只是阅读Boost.Utility。

  5. 当然!