2007年10月30日

関数の戻り値で配列の参照を返す(C++)

int型の配列へのconst参照を返す関数

const int (&GetArray())[4] {
 const static int s_array[4] = {1, 2, 3, 4};
 return s_array;
}

はっきり言って、読めません。関数名の後に配列の長さがあったりとか。。。

普通こういう場合はポインタを返すように書くと思いますが、型から「配列の長さ」の情報が失われてしまうという欠点があります。
どうしても戻り値の型に「配列の長さ」を残しておきたいという場合は使えます。

参照元

Posted by Akihiro at 16:57 | Comments (1)

2007年10月12日

"基底クラスからの派生クラスのメソッドの呼び出し" と CRTP

まずはコード。

template<class Derived>
class Base {
public:
  void Process() {
    static_cast<Derived*>(this)->SubProcess();  // 派生クラスのメソッド呼び出し
  }
};

class Hoge : public Base<Hoge> {
public:
  void SubProcess() {
    std::cout << "Hoge!" << std::endl;
 }
};

派生クラスに実装した処理を基底クラスから呼び出してます。
普通なら、SubProcessメソッドはvirtualにしてBaseクラスに定義しておくところですが、virtualにするとメソッドの呼び出しに多少なりともコストがかかってしまいます。
そのコストを避けるためのカギがCRTP (Curiously Recurring Template Pattern)です。
CRTPを使えば呼び出すメソッドが静的に決まるので、うまくいけばメソッドがインライン展開されて呼び出しコストがゼロになる可能性も期待できます。

virtualにする方が一般的でわかりやすいですが、ここぞという所で使えば威力を発揮してくれそうなイディオムです。

Posted by Akihiro at 00:13 | Comments (0)

2007年10月02日

テンプレートクラスにネストされたテンプレートクラスのテンプレートメソッド

テンプレートクラスにネストされた、テンプレートクラスのテンプレートメソッドの実装を
クラスの定義と切り離してみました。

Before:

template<class T>
struct Hoge
{
  template<class U>
  struct NestedHoge
  {
    template<class V>
    void Process()
    {
      std::cout << "Hoge Hoge!!" << std::endl;
    }
  };
};

After:

template<class T>
struct Hoge
{
  template<class U>
  struct NestedHoge
  {
    template<class V>
    void Process();
  };
};

template<class T>
template<class U>
template<class V>
inline void Hoge<T>::NestedHoge<U>::Process()
{
  std::cout << "Hoge Hoge!!" << std::endl;
}

えぐい。。。

Posted by Akihiro at 20:10 | Comments (0)