構造体の初期化


投稿ツリー



前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 | 投稿日時 2009/4/18 1:04 | 最終変更
tama  一人前   投稿数: 111
1.aのように関数へと渡すのに,リテラル使えないのって普通ですかね(配列とか出来るしコンパイラの問題?).それと2が通るのに3でコンパイルが通らないのはバグ??
一々変数とか用意するのが面倒なので,一気に書きたいけど上手く行かない^^;

#code(d,nomenu,nonumber){{{
import std.stdio, std.typecons;

alias Tuple!(string, "foo", void delegate(), "bar") VT;
alias Tuple!(string, "foo", string delegate(string), "bar") ST;

void main()
{
void a(VT v) { writefln(v); }

// 1
VT v = {"v" , { } };
writefln(v);

// 1.a
a(v);
//a({"v at a", { } });

string delegate(string) bar = (string s) { return s; };
// 2
ST s1 = {"s1" , bar };
writefln(s1.bar(s1.foo ~ ".bar"));

// 3
/*
ST s2 = {"s2" , (string s) { return s; } };
ST s2 = {"s2" , delegate string(string s) { return s; } };
writefln(s2.bar(s2.foo ~ ".bar"));
*/
}
}}}
投票数:171 平均点:4.68
返信する
前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 | 投稿日時 2009/4/18 2:35
SHOO  管理人   投稿数: 658
構造体リテラルは { } じゃなくて、

#code(d){{{
a(VT("v at a", { } ));
}}}

{ } で初期化する方法は、構造体の静的初期化というらしいです。


静的メンバの初期化子はコンパイル時に評価可能なものに限られます
というのが仕様にあるので、デリゲートリテラル(実行時に評価)がダメなのでは?

#code(d){{{
auto s2 = ST("s2" , (string s) { return s; });
}}}

こうするとうまくいくみたいですよ。


D2.0の構造体の初期化は絶対に整理が必要だと思います。

#code(d){{{
import std.stdio;

struct X1
{
int x;
alias x this;
}

struct X2
{
int x;
alias x this;
this(int a)
{
x = a;
}
}

struct X3
{
int x;
alias x this;
this(int a)
{
x = a;
}
static X3 opCall(int a)
{
X3 ret;
ret.x = a * 2;
return ret;
}
}

struct X4
{
int x;
alias x this;
this(int a)
{
x = a;
}
void opAssign(int a)
{
x = a;
}
}

struct X5
{
int x;
alias x this;
this(int a)
{
x = a;
writefln("X5 constructor");
}
static X5 opCall(int a)
{
writefln("X5 opCall");
X5 ret;
ret.x = a * 2;
return ret;
}
void opAssign(int a)
{
x = a;
writefln("X5 opAssign");
}
}


void main()
{
X1 a = 10;
writefln(a.x); // 0
a = 20;
writefln(a.x); // 20
X2 b = 30;
writefln(b.x); // 0
X3 c = 40;
writefln(c.x); // 80
X4 d = 50;
writefln(d.x); // 0

X5 x5a = 1;// X5 opCall
X5 x5b = X5(2); // X5 constructor
X5 x5c = {3}; //
x5c = 4;// X5 opAssign
}
}}}
せっかくコンストラクタがあるのだから、初期化は全部コンストラクタに任せたらいいのに…混乱します。
あと初期化時に0になるのって仕様なのかな?(alias x thisがあるのに)
投票数:166 平均点:5.42
返信する
前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 | 投稿日時 2009/4/18 20:38
tama  一人前   投稿数: 111
> 静的メンバの初期化子はコンパイル時に評価可能なものに限られます
> というのが仕様にあるので、デリゲートリテラル(実行時に評価)がダメなのでは?

http://www.digitalmars.com/d/2.0/struct.html
ここの"Static Initialization of Structs"の最後を見る限り,動的初期化にも使えるのはず,と気になったので1の部分を
#code(d){{{
VT v = {"v" , { return; } };
}}}
に変更したら,見事にコンパイルエラーにorz
どうも静的初期化内では';'を置くとコンパイルエラーになる様子(2が通って3が通らないのも同じ理由かな).ということは,現状どちらも同じく扱うにはSHOOさんの仰るとおりVT(~)の構造体リテラルを使うしかないっぽいですね.

> D2.0の構造体の初期化は絶対に整理が必要だと思います。

今はとりあえず昔からの習慣でstatic opCallを使っているけど,確かにちょっと整理したい所です.
投票数:163 平均点:4.05
返信する
前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 | 投稿日時 2009/4/19 13:27
SHOO  管理人   投稿数: 658
あるいはメンバ変数がすべて公開されている非constな構造体の初期化なら、with文とかでもいいのでは?
#code(d){{{
ST s;
with (s)
{
foo = "foo";
bar = (string str){return str;};
}
}}}


とりあえず構造体のコンストラクタを書くと構造体リテラルを使うときに呼ばれるようなので、
デフォルトではない構造体の初期化を行う場合は、
#code(d,nonumber,nooutline,nomenu){{{
ST s = x;
}}}
の形式で初期化を行わず、
#code(d,nonumber,nooutline,nomenu){{{
auto s = ST(x);
}}}
の形で初期化を行うようにすれば、コンストラクタが呼ばれるか、なければ構造体リテラルとされるはずなので、無用な混乱を避けることができるかもしれません。
D言語的には、どれか一つに限ってきっちりかっちり使うような感じにしたほうが、らしい気がする。
「コンパイラの警告レベルはいつも最大にして、 警告はエラーとして扱うように設定している人」をターゲットにしてると明言してる文章もあるくらいだし。
投票数:149 平均点:3.96
返信する

なし Re: 構造体の初期化

msg# 1.1.1.1.1
前の投稿 - 次の投稿 | 親投稿 - 子投稿なし | 投稿日時 2009/4/22 17:25
tama  一人前   投稿数: 111
http://d.puremagic.com/issues/show_bug.cgi?id=1030
Bugzilla探すと,どうもこれに近い感じが.再度fixされるのを待ってみます.
投票数:212 平均点:4.34
返信する

このトピックに投稿する

題名
ゲスト名
投稿本文

  条件検索へ


メインメニュー

ログイン

ユーザー名:


パスワード:





パスワード紛失  |新規登録

Menu