0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

enumでメンバ関数(風)呼び出し

Posted at

方針

  1. できるだけenum構文自体には手を加えない
  2. メンバ呼び出しをできるだけ簡単にしたい

実装

namespace Foo
{
	struct Hoge
	{
		enum class Type : char
		{
			Bool,
			Integer,
			Float,
			String,
			Object,
		};

		// メンバ関数用インタフェースを取得するための関数
		friend constexpr auto _(Type t)
		{
			struct {
				// 数値型だったらtrueを返すメンバ(?)関数
				constexpr bool isNumber() const
				{
					return value == Type::Integer || value == Type::Float;
				}
				Type value;
			} tmp{ t };
			return tmp;
		}
	};
}

int main()
{
	// 定数を_()で囲んで関数を呼び出すスタイル
	static_assert(_(Foo::Hoge::Type::Float).isNumber());
}

できればenum型そのものにメンバ関数を付けたいがそうもいかない
だからと言ってenum風のクラスを作るのはキツイ↓

// 元のenum構文とあまりにもかけ離れた書き方
class Type
{
	char value;
	constexpr Type(char value):value(value){}
public:
	// 必ず手動で値を振っていかなければならない
	static inline Type Bool{0};
	static inline Type Integer{1};
	...
	// enumで普通に使える演算子もいちいち用意しないといけない
	// しかもconstexpr指定してても戻り値を定数展開できないっぽい
	bool operator==(Type type) const { return value == type.value; }
};

なのでenum自体は何もいじらずそのままにアクセスする部分をどうシンプルにするかということに終始しました。
今回のようにenum型を専用の構造体などで包んでから関数呼び出しをするのは割とある方法だとは思います。
ただ今回はADLとfriend指定付きフリー関数定義を利用してenum型と関数の記述位置をできるだけ近づけつつ
あらゆるenum型で共通の記述をできるようにしました。(しかもシンプル)
名前空間もできるだけ汚染しないようにしたつもりですが、_()がフリー関数なのでここではFoo空間にシンボルが
生成されてしまっています。そこだけちょっとわかりにくいところなので注意ですね。

愚痴

今のc++の文法だとenumにメンバ関数が定義できないのは理解できるんですが、正直何とかしてほしいですよね。

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?