boostより美しい文字連結ができるシステムを思いついた!

アバター
MoNoQLoREATOR
記事: 284
登録日時: 14年前
住所: 東京

boostより美しい文字連結ができるシステムを思いついた!

投稿記事 by MoNoQLoREATOR » 13年前

varクラスのqvar()関数を追加した時に気づきました。うわっ これ画期的だ・・・!!

細かい説明は後にすることにして、まずはその文字連結方法をお見せします↓

CODE:

#define _CRT_SECURE_NO_DEPRECATE

#include "connect.h"

int main(){
	int inum = 2525;
	float fnum = 2525;
	double dnum = 2525.2525;

	printf(cnct()

using namespace std;

#ifndef _FTOS_
#define _FTOS_
string ftos(double num){
	char media[33];
	sprintf(media, "%f", num);
	string str = media;
	return str;
}
#endif

#ifndef _ITOS_
#define _ITOS_
string itos(int val, int radix = 10){
	char recep[33];
	string output = _itoa(val, recep, radix);
	return output;
}
#endif

#ifndef _CONNECT_
#define _CONNECT_

class forCNCTclass{
	string mystr;

public:

	string & content(){ return mystr; }

	forCNCTclass & operator<< (int rnum){
		mystr.append(itos(rnum) );
		return *this;
	}
	forCNCTclass & operator<< (double rnum){
		mystr.append(ftos(rnum) );
		return *this;
	}
	forCNCTclass & operator<< (string &str){
		mystr.append(str);
		return *this;
	}
	forCNCTclass & operator<< (const char *str){
		mystr.append(str);
		return *this;
	}
	forCNCTclass & operator<< (forCNCTclass &fcc){
		mystr.append(fcc.content() );
		return *this;
	}

	const char * operator<<= (int rnum){
		mystr.append(itos(rnum) );
		return mystr.c_str();
	}
	const char * operator<<= (double rnum){
		mystr.append(ftos(rnum) );
		return mystr.c_str();
	}
	const char * operator<<= (string &str){
		mystr.append(str);
		return mystr.c_str();
	}
	const char * operator<<= (const char *str){
		mystr.append(str);
		return mystr.c_str();
	}
	const char * operator<<= (forCNCTclass &fcc){
		mystr.append(fcc.content() );
		return mystr.c_str();
	}

	const char * operator< (int rnum){
		mystr.append(itos(rnum) );
		return mystr.c_str();
	}
	const char * operator< (double rnum){
		mystr.append(ftos(rnum) );
		return mystr.c_str();
	}
	const char * operator< (string &str){
		mystr.append(str);
		return mystr.c_str();
	}
	const char * operator< (const char *str){
		mystr.append(str);
		return mystr.c_str();
	}
	const char * operator< (forCNCTclass &fcc){
		mystr.append(fcc.content() );
		return mystr.c_str();
	}
};

forCNCTclass cnct(){
	forCNCTclass fcc;
	return fcc;
}

#endif
[/spoil]

cnct()関数はforCNCTclassオブジェクトを返しているだけです。実は、そこがミソなのです。
printf(forCNCTclass fcc << inum << fnum);
単純に考えると、上記のように書きたい所ですが、これではコンパイルエラーになってしまいます。
しかし、関数から返ってきたオブジェクトであれば全く問題ありません。
これにより、非常に美しい文字連結が可能になりました。


使用方法詳細

cnct()関数を呼べば、後は<<演算子を使ってどんどん文字・数値(int,double,string&,const char*)を連結してゆけます。最後の連結のときだけ<<=演算子又は<演算子(動作は全く同じですのでお好みの方をご使用ください)を使用することでconst char*型が返され、めでたく連結された文字列を渡すことができます。



以上です。
ここまで興奮して書いたのですが、もしかしたらもう既にこのシステムは発見されているかもしれませんねぇ・・・。
最後に編集したユーザー MoNoQLoREATOR on 2011年11月08日(火) 23:40 [ 編集 1 回目 ]

アバター
a5ua
記事: 199
登録日時: 14年前

RE: boostより美しい文字連結ができるシステムを思いついた!

投稿記事 by a5ua » 13年前

http://marupeke296.com/TOOL_No7_DixStr.html
このあたりが似た感じですかね。

リンク先の実装と同様に、連結する関数はテンプレートにすると、シンプルになると思います。

beatle
記事: 1281
登録日時: 13年前

Re: boostより美しい文字連結ができるシステムを思いついた!

投稿記事 by beatle » 13年前

std::cout<<"inum="<<inum<<"\nfnum="<<fnum<<"\ndnum="<<dnum<<"\n";
とやるのと比べて、MoNoQLoREATORさんの方法の優れている点を教えて下さい。

ISLe
記事: 2650
登録日時: 14年前

Re: boostより美しい文字連結ができるシステムを思いついた!

投稿記事 by ISLe » 13年前

std::ostringstreamを使えばもっと簡単に実装できる気がします。

アバター
MoNoQLoREATOR
記事: 284
登録日時: 14年前
住所: 東京

Re: boostより美しい文字連結ができるシステムを思いついた!

投稿記事 by MoNoQLoREATOR » 13年前

>>a5uaさん
連結する関数をテンプレートにすると、何がどのように変わるのでしょうか?

>>beatleさん
今回の目的は、文字連結した後”表示すること”ではなく”const char*型ポインタを返すこと”です。

>>ISLeさん
それはcnct()の返り値をostringstreamにするという意味ですよね?
そうすると<<=演算子を使ってconst char*型ポインタを返すという便利な機能が使えなくなってしまうので賛成できません。(cnct()<<"").str().c_str()というように記述するのはとてもめんどうだと私は思うわけですよ。

アバター
a5ua
記事: 199
登録日時: 14年前

RE: boostより美しい文字連結ができるシステムを思いついた!

投稿記事 by a5ua » 13年前

先ほどのリンク先(http://marupeke296.com/TOOL_No7_DixStr.html)のコードとほぼ同じですが、
ostringstreamを使って引数を文字列化しています。(
#include

// 文字列に変換する
template
std::string to_str(const X &x)
{
std::ostringstream oss;
oss
my_string_buffer_1 &operator
#include

// 文字列に変換する
template
std::string to_str(const X &x)
{
std::ostringstream oss;
oss
explicit my_string_buffer_2(const X &x)
: m_str(to_str(x))
{
}

template
my_string_buffer_2 &operator()(const X &x)
{
m_str += to_str(x);
return *this;
}

const char *c_str() const
{
return m_str.c_str();
}

private:
std::string m_str;
};
[/code]

以下サンプルコード
► スポイラーを表示
書いてて気づいたのですが、暗黙の型変換では、以下のケースに対応できないので、
使用する演算子を変えて、const char *を返すというのは、面白いと思いました。

CODE:

int main()
{
	int inum = 2525;
	float fnum = 2525;
	double dnum = 2525.2525;

	// NG: const char * への変換が行われない
	std::printf("%s", my_string_buffer_1()<<"inum="<<inum<<"\nfnum="<<fnum<<"\ndnum="<<dnum<<"\n");

	// OK: 明示的な変換
	std::printf("%s", my_string_buffer_2("inum=")(inum)("\nfnum=")(fnum)("\ndnum=")(dnum)("\n").c_str());
}

アバター
MoNoQLoREATOR
記事: 284
登録日時: 14年前
住所: 東京

Re: boostより美しい文字連結ができるシステムを思いついた!

投稿記事 by MoNoQLoREATOR » 13年前

なるほど、たしかにテンプレートを使用すると簡単につくれますね。ISLeさんはこれが言いたかったのですね。失礼しました。

ところで、
operator const char *() const
というのは初めて見たのですが、これはどのような文法なのでしょうか?

beatle
記事: 1281
登録日時: 13年前

Re: boostより美しい文字連結ができるシステムを思いついた!

投稿記事 by beatle » 13年前

constメンバ関数については
http://www.geocities.jp/ky_webid/cpp/language/020.html
を参考にしてください。

戻り値型 メソッド名() const { ... }
とすることで、このメソッドはインスタンスの状態を変えないという意味になります。

beatle
記事: 1281
登録日時: 13年前

Re: boostより美しい文字連結ができるシステムを思いついた!

投稿記事 by beatle » 13年前

せっかく書いたので参考にしてください。
myostringstreamは
#include

class myostringstream
{
public:
template
myostringstream& operator
const char* operator
const char* operator <(const T& obj)
{
return (*this) <<= obj;
}

private:
std::ostringstream oss_;
std::string buf_;
};

typedef myostringstream cnct;

int main()
{
int inum = 2525;
float fnum = 2525;
double dnum = 2525.2525;

printf(cnct()<<"inum="<<inum<<"\nfnum="<<fnum<<"\ndnum="<<dnum<"\n"); //出力
}
[/code]
最後に編集したユーザー beatle on 2011年11月10日(木) 08:35 [ 編集 2 回目 ]

アバター
MoNoQLoREATOR
記事: 284
登録日時: 14年前
住所: 東京

RE: boostより美しい文字連結ができるシステムを思いついた!

投稿記事 by MoNoQLoREATOR » 13年前

見直しているといくつかの事に気づきました。

まず
operator const char *() const
という文法なのですが、これが「キャストをオーバーロード」だったのですね。
この瞬間、私の頭の中に仮説が出来上がりました。
int x = "\(^o^)/";
例えば上記のコードを書いた場合、内部で暗黙的に型変換が試みられる↓
int x = (int)"\(^o^)/";
この場合コンパイルに失敗するわけですが、重要なのはそこではなく、今まで耳にしていた「暗黙的な型変換」という動作は、可能な場合にのみ行われるのではなく、常に行われている(キャスト演算子が自動的に付加される)のだろうという点です。
異なる型同士の演算には常にキャスト演算子が自動的に付加されるということは、そのキャスト演算子をオーバーロードすれば自由自在に型変換させることができるということ・・・!
革命だ!と思いました。
ちなみに返値の型が指定されていない上に返値を返していますが、これは「キャストをオーバーロードする場合」に特別に認められていることなのですか?

次に、
クラス名()<<"inum="......
としている点です。クラスをインスタンス化したら、必ず名前をつけなければならないのだと思っていたのですが、そうでもないということ・・・ですよね?
そしてもう1つわかったことがあります。
ostringstreamの<<演算子を使った場合の返値はbasic_ostreamであり、.str()メンバ関数は使えないということです。つまり
(ostringstream()<<"\(^o^)/").str();
というようなことはできないということですね。ちなみにostringstreamからbasic_ostreamにキャストすることはできませんでした。
ところで、以下のソースコードでは不正アクセスは起こりませんよね?

CODE:

	string &s = ostringstream().str();
	printf(s.c_str() );

beatle
記事: 1281
登録日時: 13年前

RE: boostより美しい文字連結ができるシステムを思いついた!

投稿記事 by beatle » 13年前

MoNoQLoREATOR さんが書きました: ところで、以下のソースコードでは不正アクセスは起こりませんよね?

CODE:

	string &s = ostringstream().str();
	printf(s.c_str() );
まあ試してみればいいんじゃないですか?
ちなみにgccではコンパイルさえできませんけれども。
最後に編集したユーザー beatle on 2011年11月10日(木) 23:19 [ 編集 1 回目 ]