こんにちは、高木です。
ここのところTcl/Tkのラッパークラスを作っています。前回はwidgetクラスを派生してlabelクラスを作りました。Tkには多数のウィジェットがありますが、派生クラスはほとんど同じコードの連続になります。こういうときには以前連載していたPHPによる前処理が便利です。
最初に前回作ったlabelクラスをもう一度確認しておきましょう。
| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | namespace tk {   class label : public widget   {     static constexpr char8_t type[] = u8"label";   public:     label(const widget& parent, const tcl::obj& name, std::initializer_list<tcl::obj> options)       : widget(type, parent, name, options)     {     }     ~label() noexcept = default;     label(const label&) = default;     label(label&&) = default;     label& operator=(const label&) = default;     label& operator=(label&&) = default;   private:     virtual tcl::obj do_type() const     {       return type;     }   }; } | 
ほかのウィジェット、たとえばbuttonのラッパークラスを作るにはどうすればいいかを考えてみます。どうやら「label」となっているところを「button」に単純に置き換えるだけでも問題なさそうです。
単純に置き換えるだけでいいなら、labelクラスのコードをPHPの文字列として保持しておいて、PHPのstr_replace関数で置換するだけでもよさそうです。ただ、それではあまりにも融通がききませんので、「label」にあたる部分を$typeという変数にして埋め込むことを考えましょう。
その方針で作ったPHPの関数が下記になります。
| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <?php function make_widget_class(string $type) : string {   return <<<EOT   class $type : public widget   {     static constexpr char8_t type[] = u8"$type";   public:     $type(const widget& parent, const tcl::obj& name, std::initializer_list<tcl::obj> options)       : widget(type, parent, name, options)     {     }     ~$type() noexcept = default;     $type(const $type&) = default;     $type($type&&) = default;     $type& operator=(const $type&) = default;     $type& operator=($type&&) = default;   private:     virtual tcl::obj do_type() const     {       return type;     }   }; EOT; } ?> | 
あとは、生成するウィジェットの種類の数だけmake_widget_class関数を呼び出してあげればOKです。今回はとりあえずlabelとbuttonだけにしますが、種類が増えても同じことです。
| 0 1 2 3 4 5 6 7 | <?php foreach ([ 'label', 'button' ] as $type) {   echo make_widget_class($type); } ?> | 
これでウィジェットクラスを量産できるようになりました。もし、特別なメンバーを追加する必要が出てきた場合は、make_widget_class関数に引数を追加してコールバック関数を渡してあげれば対応できますね。
現状のwidgetクラスでは、オプションの指定をコンストラクタでしか行うことができません。次回はTcl/Tkのコマンドでいうconfigureとcgetに相当するメンバー関数を追加していくことにします。


![[迷信] freeでメモリを開放する](https://www.kijineko.co.jp/wp-content/uploads/2021/06/3649452_s.jpg)



