LoginSignup
1
0

More than 1 year has passed since last update.

ポインタ変数に対するメソッド呼び出し時のnullチェック共通化をChatGPTに教えてもらった

Posted at

概要

やりたいこと:
C++ で, ポインタ変数で持っているインスタンスに対してメソッドを呼び出したい. 当然nullチェックが必要だが, メソッドがたくさんあるときに毎回チェックを書くのはだるい.

やったこと:
自分なりにいろいろとぐぐってみたがいまいちこれという解にたどり着けなくて, ためしに最近流行りのChatGPTさんに聞いてみたらほぼ期待通りの結果が得られてすごかった, という記録.

TL;DR

これが欲しかった関数.

tldr.cpp
#include <functional>

// ヘルパー関数定義
void callMethodIfValid(SomeClass* ptr, std::function<void(SomeClass*)> func) {
  if (ptr != nullptr) {
    func(ptr);
  }
}

// 呼び出し例. ラムダ式で呼び出したい処理を渡す.
SomeClass* ptr;
callMethodIfValid(ptr, [](SomeClass* p) {
  p->method1();
});

ChatGPT との Q&A

以下, 引用文はChatGPTへのクエリ, コードブロックはChatGPTからの返答である(コードに付随する説明文はばっさりと省略).

Q1. Nullチェックの基本処理

C++で, あるクラスのポインタ変数がnullptrならば無視し, 有効ならばメソッドを呼ぶ, という処理はどのように書けますか?

A1.

answer1.cpp
if (ptr != nullptr) {
  ptr->method();
}

Nullチェックの基本.

Q2. Nullチェックを共通化したい

ptrにメソッドが大量に生えており, 確認のif文を大量にコピーしなければならないとすると, 重複を避けるうまい方法はありますか?

A2.

answer2.cpp
void callMethodIfValid(SomeClass* ptr) {
  if (ptr != nullptr) {
    ptr->method();
  }
}

雰囲気はそれっぽいが, method()が埋め込みなので意図とは異なる.

Q3. メソッド名を変数にしたい

呼びたいmethod()をcallMethodIfValid の外から指定したい場合, どのように書けばよいですか

A3.

answer3.cpp
#include <functional>

void callMethodIfValid(SomeClass* ptr, std::function<void(SomeClass*)> func) {
  if (ptr != nullptr) {
    func(ptr);
  }
}

なるほど?

sample3.cpp
SomeClass* ptr = getPointer(); // ptrは、あるクラスのポインタ変数

callMethodIfValid(ptr, [](SomeClass* p) {
  p->method1();
});

callMethodIfValid(ptr, [](SomeClass* p) {
  p->method2();
});

これだあああすごいいい

応用など

教えてもらったコードを参考に, 外から変数をキャプチャしたりautoで型名を省略したり.

custom.cpp
int param;

callMethodIfValid(ptr, [param](auto* p) {
  p->method1(param);
});

コード例は省略するが, メソッド呼び出しに成功したかどうかのbool値を返すように変更するのも簡単.
ptrをメンバに持つクラスを作ってそこに生やすのも良さそう.
あと今回自分の用途だと不要だったけど, メソッドの戻り値が欲しい場合はtemplate化してoptionalで受ければ良さそう.

use_return.cpp
#include <optional>

template <typename T>
std::optional<T> callMethodIfValid(SomeClass* ptr, std::function<T(SomeClass*)> func) {
    if (ptr != nullptr) {
      return func(ptr);
    } else {
      return std::nullopt;
    }
};

…こうなってくると結局外でhas_valueとかが必要になってきちゃいそうだけど, でもメソッド呼び出しとは別のタイミングでチェックできると嬉しいケースもあるかもしれない(適当).

ChatGPTでは同一セッション中に前に出てきたワードを用いて対話ができるので, 意図とちょっと違う結果が返ってきても粘って話を続けると色々得られてすごい. 今後も活用していきたい.

リンク

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0