c++ - パラメータ - 名前付き引数 javascript



C++の名前付きパラメータのイディオムを使用する方がいいですか? (4)

私はWindows用のGUIライブラリを開発してきました(個人的なプロジェクトとして、有用性の願望はありません)。 私のメインウィンドウクラスでは、いくつかのオプションは共有されており、その他は特定のタイプのウィンドウ(ダイアログなど)に固有のものであるため、オプションクラスの階層を設定しました( 名前付きパラメータの慣用名を使用)。

Named Parameter Idiomが動作する方法では、パラメータクラスの関数は呼び出されたオブジェクトを返さなければなりません。 問題は、階層内で、それぞれが異なるクラス(標準ウィンドウ用のcreateDialogOptsクラス、ダイアログ用のcreateDialogOptsクラスなど)でなければならないことです。 私はすべてのオプションクラスのテンプレートを作成することでそれを処理しました。 ここに例があります:

template <class T>
class _sharedWindowOpts: public detail::_baseCreateWindowOpts {
    public: ///////////////////////////////////////////////////////////////
    // No required parameters in this case.
    _sharedWindowOpts() { };

    typedef T optType;

    // Commonly used options
    optType& at(int x, int y) { mX=x; mY=y; return static_cast<optType&>(*this); }; // Where to put the upper-left corner of the window; if not specified, the system sets it to a default position
    optType& at(int x, int y, int width, int height) { mX=x; mY=y; mWidth=width; mHeight=height; return static_cast<optType&>(*this); }; // Sets the position and size of the window in a single call
    optType& background(HBRUSH b) { mBackground=b; return static_cast<optType&>(*this); }; // Sets the default background to this brush
    optType& background(INT_PTR b) { mBackground=HBRUSH(b+1); return static_cast<optType&>(*this); }; // Sets the default background to one of the COLOR_* colors; defaults to COLOR_WINDOW
    optType& cursor(HCURSOR c) { mCursor=c; return static_cast<optType&>(*this); }; // Sets the default mouse cursor for this window; defaults to the standard arrow
    optType& hidden() { mStyle&=~WS_VISIBLE; return static_cast<optType&>(*this); }; // Windows are visible by default
    optType& icon(HICON iconLarge, HICON iconSmall=0) { mIcon=iconLarge; mSmallIcon=iconSmall; return static_cast<optType&>(*this); }; // Specifies the icon, and optionally a small icon
    // ...Many others removed...
};

template <class T>
class _createWindowOpts: public _sharedWindowOpts<T> {
    public: ///////////////////////////////////////////////////////////////
    _createWindowOpts() { };

    // These can't be used with child windows, or aren't needed
    optType& menu(HMENU m) { mMenuOrId=m; return static_cast<optType&>(*this); }; // Gives the window a menu
    optType& owner(HWND hwnd) { mParentOrOwner=hwnd; return static_cast<optType&>(*this); }; // Sets the optional parent/owner
};

class createWindowOpts: public _createWindowOpts<createWindowOpts> {
    public: ///////////////////////////////////////////////////////////////
    createWindowOpts() { };
};

それは動作しますが、わかるように、それぞれの関数の戻り値型の型キャスト、余分なテンプレートクラスなどが余分な作業を必要とします。

私の質問は、この場合、名前付きパラメータのイディオムを実装する簡単な方法があります。余分なものをすべて必要としないものですか?

https://ffff65535.com


どうですか?

template <class T>
class _sharedWindowOpts: public detail::_baseCreateWindowOpts {

protected: // (protected so the inheriting classes may also use it)

    T & me() { return static_cast<T&>(*this); }               // !

public:
    // No required parameters in this case.
    _sharedWindowOpts() { };

    typedef T optType;

    // Commonly used options
    optType& at(int x, int y) { mX=x; mY=y; return me(); };   // !
    // ...
};

テンプレートは熱いです。

しかし、POP(Plain old Polymorphism)は死んでいない。

なぜ、(スマート)ポインタをサブクラスに返さないのですか?


私はこの答えに惚れているのかどうかはわかりませんが、ここでテンプレート引数の控除を使用する可能性があります。 NOTE私は私のコンパイラを持っていません。誰かがそこを騒がしくしない限り、明日二重チェックします。

class sharedWindowOpts
{
public:

  sharedWindowOpts() {};

  // Commonly used options
  template <class optType>
  static optType& at(int x, int y, optType& opts) { opts.mX=x; opts.mY=y; return opts; };

  template <class optType>
  static optType& background(HBRUSH b, optType& opts) { opts.mBackground=b; return opts; };

  // etc...
}

class createWindowOpts : public sharedWindowOpts
{
public:
  createWindowOpts() : sharedwindowOpts() {};

  // These can't be used with child windows, or aren't needed
  template <class optType>
  static optType& menu(HMENU m, optType& opts) { opts.mMenuOrId=m; return opts; };

  template <class optType>
  static optType& owner(HWND hwnd, optType& opts) { opts.mParentOrOwner=hwnd; return opts; };
 }

次に、CreateWindowを次のように呼び出します。

CreateWindow( createWindowOpts::owner(hwnd,
              createWindowOpts::at(0, 100,     // can use createWindowOpts because it doesn't hide sharedWindowsOpts::at
              createWindowOpts::menu(hmenu, createWindowOpts() ) ) ) );

もちろん、これについての厄介なことは、構文とすべての余分な括弧を呼び出す静的メソッドを使用しなければならないことです。 静的メンバー関数を非メンバー関数に置き換えると、これを排除できます。 しかし、それは型キャストと追加のテンプレートクラスを避けています。

個人的には、あなたの方法と同じようにライブラリの中に奇妙なコードを載せたいと思っています。


継承の逆順でメソッド呼び出しをチェーンするだけでいいですか?

だから、あなたの例では、

ウィンドウウィンドウ= CreateWindow( "foo")。メニュー(hmenu).owner(hwnd).at(0,0).background(hbr);

私はそれが100%透明ではないことを認識していますが、少し簡単でほとんど正しいと思われます。





named-parameters