2

次の関数テンプレートについて考えてみます。

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

値渡しのセマンティクスは、Tたまたま整数型、または少なくともコピーが安価な型である場合に意味があります。一方、pass-by- [const] -referenceセマンティクスを使用Tすることは、コピーするのにコストのかかるタイプである場合に、より理にかなっています。

あなたがライブラリを書いていると少しの間仮定しましょう。理想的には、ライブラリの実装者としてのあなたの仕事は、可能な限り一般的で効率的なクリーンな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. 最後に、これは正気なことでもありますか?

*プロファイルされていません。;)

4

1 に答える 1

2
  1. はい。いつも。自分で使っています。
  2. はい、Boost.UtilityのCallTraitsを使用してください:)

    使用法は...

    template <typename T>
    void foo(boost::call_traits<T>::param_type param)
    {
        // Use param
    }
    
  3. 私の知る限り、クラス以外のテンプレートは、高速でない限り、値渡しされます。部分的なテンプレートの特殊化のおかげで、比較的簡単にカスタマイズできます。

  4. 申し訳ありませんが、あなたがしたことを実際には読んでいませんでした。数か月前に私が経験したこととまったく同じように見えました。したがって、これに実際に答えることはできません。私の推奨事項は、Boost.Utilityを読むことです。

  5. もちろん!

于 2010-07-07T04:10:44.347 に答える