6
8

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.

C++でC#のreadonlyを実装できなかった話

Posted at

Readonly

この記事は私以外にはReadonlyです。

C#にはreadonlyという修飾子がありまして…

readonly.cs
class Test
{
    public const    int value_c = 10;
    public readonly int value_r = 20;

    public Test(){
        value_r = 10;
    }
    public Test(int v)
    {
        value_r = v;
    }
}

このように、readonlyconstの機能である宣言時に初期化に加え、コンストラクタ内での初期化も許可されています。その他の点はconstと同様です。

C++での実装

というわけでゴリゴリ書きました。
C++にはfriendというアクセスを許可する修飾子がありまして…
それで、パパパっと親クラスのコンストラクタのみ許可して、終わりっ!

Readonly.cpp

template <class Parent,class T>
class ReadOnly {
public:
	typedef T value_type;
	friend Parent::Parent();

private:	
	T instance;
	
	value_type& operator=(const value_type& v) {
		instance = v;
		return instance;
	}

public:
	//constructor
	ReadOnly() {}
	ReadOnly(const T& v) : instance(v){}
};

「このコードは実行できませんのでご注意を」
まずは代入ができるか確認して、できたら暗黙キャストでも入れよう。
テストクラスはこんな感じ


class test{
public:
	ReadOnly<test,int> read;
	test(){
		read = 10;
	}
};

問題

friend Parent::Parent();にて
error: C++ requires a type specifier for all declarations

前方宣言によって使用できるのは型の宣言のみで内部実装は見えない。
コンストラクタを実装していない可能性もあり得る。よってtestクラスを先に書く必要がある。

他にもいろいろと問題点はあるが、実装依存のデータ構造はいろいろと破綻しているので、実装しない。別にファイル分割が面倒くさいとか、Macにしてからvimrcの調子が悪いとか、そういうことではない。

まとめ

この問題を解決するのはわりと難しそうだ。
SFINAEでなんとかと思ったが、そもそも#include前に定義しないと全部スコープ外になるし、今回はそういう問題じゃない。

今日はもう無理…

メモ

・friendは、定義されてない型や関数にすることは可能
・スコープ解決演算子(::)の左辺は必ず存在しないとダメ
・前方宣言は、メンバの定義は参照できない
・コンストラクタのオーバーロード全てに対応できるのか?

・よってコンストラクタのfriendは、Readonlyクラスより先に定義されている必要がある。
・このままではデータ構造としては非常に使い難いものになってしまう。

6
8
2

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
6
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?