ペイントソフト開発日誌

日々の出来事を殴り書き

QtCreatorのClang-Tidyをカスタマイズしてコーディングを効率化しよう

目次

はじめに

突然ですが皆さんはコーディングにどのエディタを使っているでしょうか。
私はメインがQtCreatorでたまにVSCodeを使っています。
Qtユーザーしか使っていない印象ですが、良いところがたくさんあるのでこの記事ではその一つを紹介します。
メインはClang-Tidyの話なのでQtCreatorに興味がない方もお付き合いいただけると嬉しい。

Clang-Tidyって何?

Clang-TidyはC/C++用の静的解析ツールです。
これを使うとプログラムのエラーやスタイル違反、ベストプラクティスの指摘などコードの質を上げることができます。 昔のQtCreatorでは構文解析にClangは使っていなかったのですが、いつからかClangが使われるようになりCPUリソースを馬鹿食いモダンなC++も正確に構文解析できるようになりました。
Clang-Tidyにはチェック項目が数多くあり、QtCreatorではそれらをカスタマイズすることができるので、手順を以下に紹介します。

Clang-Tidyの設定手順

Qt Creatorのバージョンは13.0.0を使用しています。

  1. [編集] > [Preferences...] > [解析] > [Clang Tools] > [Run Options] > [Diagnostic configuration] から[診断設定]のダイアログを開きます
  2. ビルトインの設定を右上の[コピー...]から複製します
  3. あとは下の[Clang-Tidy Checks]のタブから有効にしたい項目にチェックを入れるだけです

modernize-use-trailing-return-typeをONにしよう

チェックを入れるだけ、と言われても数が多すぎて何が使える項目なのか見当がつかないと思います。(かくいう私もほとんど知りません)
そこで今回はmodernize-use-trailing-return-typeを紹介します。
ここからの内容は前回の記事の補足にもなるので良ければこちらもどうぞ。 rough-paint.hatenablog.com

前回の記事では戻り値型の後置記法の話を書いたのですが、以下の問題を挙げました。

Q.IDEの自動生成が対応していない
Q.タイプ数増えるから嫌
Q.既存の実装を書き換えるのダルい

これに対する私の回答は「Clang-Tidyで後から一括で書き換える」です。
Clang-Tidyは一部の内容についてはコードを直してくれる機能があります。
ちょっと力技ですが、楽なのでauto->を直書きするよりもこっちを使うことが多いです。
QtCreatorでこの設定を有効にすると以下のようになります。

Before After

警告も出してくれるので一目でわかるのも嬉しい。
左クリック > [Analize Current File with Clang-Tidy] を実行して表示される画面から、[Select Fixits] > [Apply Fixits]を押すことでコードを直してくれます。

ここではQtCreatorでのやり方を紹介しましたが、Visual StudioVSCodeでも使えるようなので、みんなも使ってみよう。

C++erは全員戻り値型の後置記法を使おう

目次

「戻り値型の後置記法」って何?

C++11から導入された言語仕様です。 タイトルの呼び方は自分が勝手に使っているだけで、英語圏だと「trailing-return-type」がよく使われるらしい。 cpprefjp.github.io

この仕様を使うと例えば以下のようなコードが

int Add(int a, int b)
{ return a + b; }

このようになります。

auto Add(int a, int b) -> int
{ return a + b; }

何が嬉しいの?

この仕様はC++メタプログラミングで戻り値型の推論を簡単に行う目的で使用されます。
なんだ、そんなC++上級者のための機能なんて下々の人間には関係ないじゃん、とお思いかもしれませんが、この機能にはもう一つわかりやすい大きなメリットがあるのです。
それはズバリ...

関数名でインデントが揃えやすい

例えば以下のようなクラスがあったとします。

class Human
{
public:
    Human(int age, const std::string& name);

    int GetAge() const;
    std::string GetName() const;

private:
    int m_age;
    std::string m_name;
};

このクラスでは2つのメンバ関数がありますが、関数名の位置がずれているため気持ち悪さを感じるかもしれません。

class Human
{
public:
    Human(int age, const std::string& name);

    int         GetAge() const;
    std::string GetName() const;

private:
    int m_age;
    std::string m_name;
};

スペースを入れて関数名の位置を揃えました。
いや~、プログラムがきれいになるのは気持ちがいいですね。
ん?子供の名前の一覧を取得するメンバ関数が欲しい?...しょうがないなぁ

class Human
{
public:
    Human(int age, const std::string& name);

    int         GetAge() const;
    std::string GetName() const;
    std::vector<std::string> GetChildNameList() const;

private:
    int m_age;
    std::string m_name;
    std::vector<std::string> m_childNameList;
};

文章で説明したほうが早かったかもしれませんね。
つまり、関数を定義する際にそのまま並べてしまうと、関数名が揃わないので可読性が下がってしまう。
かといって、関数名で揃えてしまうと、後々名前が長い戻り値型の関数を追加するときに困ってしまう、というジレンマが起きているのです。
別案として戻り値型で改行する方法もありますが、行数がかさむのでスマートとは言えません。
しかし「戻り値型の後置記法」を使うと...

class Human
{
public:
    Human(int age, const std::string& name);

    auto GetAge() const -> int;
    auto GetName() const -> std::string;
    auto GetChildNameList() const -> std::vector<std::string>;

private:
    int m_age;
    std::string m_name;
    std::vector<std::string> m_childNameList;
};

この2つの問題をスマートに解決することができます。 いくつか問題点もありますが、見栄えがいいので自分は普段からこの書き方で実装しています。

問題点

Q.戻り値型が見づらい
A.耐えてください。

Q.IDEの自動生成が対応していない
Q.タイプ数増えるから嫌
Q.既存の実装を書き換えるのダルい
A.これはある程度どうにかできるので次回紹介します。


<追記>
解決方法も書きました。 rough-paint.hatenablog.com

初投稿

いらっしゃいませ、1名様でよろしいでしょうか。

空いているカウンター席へどうぞ。

 

こちらのブログは私が趣味で開発しているペイントソフトのことを書き留めようと始めました。

進捗から実装に関してのこと、はたまた関係ない日記まで気が向いたら書いていこうと思います。

以下FAQ。

 

Q. 今の進捗は?

A. こんな感じ

起動画面

レイヤー機能や線も引けるようになってるよ

 

Q. OSS?いつから書いてるの?てかGithubやってる?

A. 今のところコードを公開する予定はないよ

とはいえ部分的にはこのブログで公開していくつもり。

最初のコミットは2022年の6月。

Githubは使ってるからそのうちプロフィールに書いとくね。

 

Q. 開発環境教えて

A. Windows PCでプログラミング言語C++を使っているよ

あとはビルドツールにCMake、GUIライブラリにQtとか使っているよ。

詳細は後で記事にするね。

 

Q. モチベーションは何?お金?

A. いつか販売したい気持ちもあるけど、自分が作ったソフトで絵を描きたいってのが大きいかも

 

 

だいたい気になることは書けたんじゃないでしょうか。

なるべく続けていこうと思うので、またのご来店をお待ちしています。