「一流グラフィックスプログラマへの道~リアルタイム編~」の感想及びメモ。
はじめに
いろいろとプロジェクトを作っているのですが、実は私はゲームのグラフィックスに興味があります。
そしてゲーム開発界隈に入ってから最終的にはローレベルを弄りまくるグラフィックスプログラマになりたいです。
(エンジンを底を触りながらグラフィックスなんてちょっととんでもなさそうですけどね)
それで一昔前に「一流グラフィックスプログラマへの道~リアルタイム編~」という記事を発見してお読みしました。今から3年の前の記事ですが、ローレベルのグラフィックスプログラマを目指している私には物凄く役に立ちそうな記事でしたので精読させていただきました。それで私が感じた感想やメモなどをブログにて書いていきたいと思います。
続きを読むModern C++ Design Chapter 2 Memo (1)
2.2 Partial Template Specialization
- クラスに対しての部分特殊化は通じるが、メンバー関数や一般関数での部分特殊化は出来ない。
- 関数をテンプレートに対して部分的に特殊化したい場合なら、以下のようにオーバーローディングをするしかない。
template <class T, class U> T Func(U obj); template <class U> void Fun<void, U>(U obj); // Prohibited. template <class T> T Fun(Window obj); // Legal (overloading)
2.3 Local Classes
void Func() { class Local { // ... Member variables ... // ... Member function definitions ... }; // Code using local... }
- 関数の中身にクラスの定義がある場合、このクラスはローカルクラスという。
- ローカルクラスは静的変数が定義出来ない。そして関数の外からはローカルクラスの変数には接近できない。
- ローカルクラスは関数の外からはローカルクラスを継承出来ない。
ローカルクラスを使用し、インタフェースを継承したクロージャーなどを実装することが出来る。
class Interface { public: virtual void Fun() = 0; }; template <class T, class P> std::unique_ptr<Interface> MakeAdapter(const T& obj, const P& arg) { class Local : public Interface { public: Local(const T& obj, const P& arg) : obj_(obj), arg_(arg) {}; virtual void Fun() { obj_.Call(arg_); } private: T obj_; P arg_; }; return std::make_unique<Local>(obj, arg); }
2.5 Type-to-Type Mapping
#include <cstdint> #include <vector> template <typename TFrom, typename TTo> class Conversion { using TSmall = char; class DBig { char dummy[2]; }; static constexpr TSmall Test(const TTo&); static constexpr DBig Test(...); static constexpr TFrom MakeT(); public: static constexpr bool exists = sizeof(Conversion::Test(MakeT())) == sizeof(TSmall); }; template <typename TFrom, typename TTo> class ConversionExt : public Conversion<TFrom, TTo> { public: static constexpr bool sameType = false; }; template <typename TFrom> class ConversionExt<TFrom, TFrom> : public Conversion<TFrom, TFrom> { public: static constexpr bool sameType = true; }; static_assert(Conversion<double, int>::exists, ""); static_assert(Conversion<char, char*>::exists, ""); static_assert(Conversion<std::size_t, std::vector<int>>::exists, ""); class Base {}; class Derived final : public Base {}; class NotDerived final {}; static_assert(Conversion<Derived, Base>::exists, ""); static_assert(Conversion<Base, Derived>::exists, ""); static_assert(Conversion<NotDerived, Base>::exists, ""); template <typename T, typename V> constexpr bool IsSuperClass = (ConversionExt<T, V>::exists == true) && (ConversionExt<T, const void*>::sameType == false); static_assert(IsSuperClass<const Derived*, const Base*>, ""); static_assert(IsSuperClass<const NotDerived*, const Base*>, ""); static_assert(IsSuperClass<const Base*, const Base*>, ""); template <typename T, typename V> constexpr bool IsSuperClassStrict = IsSuperClass<T, V> && (ConversionExt<T, V>::sameType == false); static_assert(IsSuperClassStrict<const Derived*, const Base*>, ""); static_assert(IsSuperClassStrict<const NotDerived*, const Base*>, ""); static_assert(IsSuperClassStrict<const Base*, const Base*>, "");
C++静的分析ツールのCppDependを使用してみた。
CppDependとは
CppDependはCまたはC++のプロジェクトのコードを分析してコードの維持管理を容易くできるようにする分析ツールです。これを使うによって下記のことが把握できます。
- コードの総量(LOC)が把握できる。
- 総コードとコメントとの割合が見れる。
- プロジェクトに定義したタイプ、メソッドなどの数が確認できる。
- レガシーコードの管理がしやすくなる。
- プロジェクトのコード規則に違反したコードがあるかが確認できる。
- 技術的負債の比率が確認できる。
- などなど…
実は以前に知り合いからから進められましたが、今更使うことになりました。今日使い始めましたし、お金もないから体験版をダウンロードしてしばらく使いたいと思います。
実はGitHubなどでオープンソース開発の目的で使用しているなら無料で使える方法があるようです。
プロジェクトに準じた文書とアクティビティを用意して、CppDependをサービスしている会社に送って無料で使わせたいと頼めば無料で使えるらしいです。ツールの定価はおよそ599ドルになりますし、個人の開発者はこのルートを通してツールを無料に使うようにするほうが良いと思います。
実際に使用して見ました。
最初分析をするのにおよそ10分くらい掛かりました。そしてこのように分析した結果の画面が見れます。このようにLOC、技術的負荷などが見れるようになります。
そしてこの画面でけじゃなくて、数値をクリックしてどの部分のどのコードが正しいかそれとも直すべきなのかをお知らせしてくれます。
例えば、右列のRules > Critical
をクリックしたらこのような画面が表示され、そして直すべきのコードを見せるようにしてくれます。
そしてMetrics
メニューではメソッドかタイプごとのLOCまたは複雑度を色で見せてくれます。全体の様相を把握したいならこれを見るほうが良いでしょうね。
結論
技術的負荷を指すDebt
は日々にどんどん増加するそうです。
規則違反、臭いコード(Code smell)、大きすぎるタイプなどが技術的負荷に当てはまります。ですから静的コード分析を行ってこのDebt
を減らすようにリファクタリングなどをするほうが良いかもしれないですね。