読者です 読者をやめる 読者になる 読者になる

【D言語】型修飾子の組み合わせ【const(immutable(T))】

ふと、型修飾子を組み合わせるとどうなるのか気になったので、調べて見ました。


型修飾子の組み合わせというのは、以下のようなものです。

これらの中で、実際に意味を持つものは少なそうですね・・・ dmdはこれらをどのように扱っているのか、以下のコードで調べて見ました。


import std.typetuple, std.stdio;

template ConstOf(T)       { alias        const(T)  ConstOf;       }
template SharedOf(T)      { alias       shared(T)  SharedOf;      }
template ImmutableOf(T)   { alias    immutable(T)  ImmutableOf;   }

alias QualList = TypeTuple!(ConstOf, SharedOf,  ImmutableOf);
enum  NameList = ["const", "shared", "immutable"];
struct T{}

void main()
{
    foreach(i, Qual1; QualList)
    {
        foreach(j, Qual2; QualList)
        {
            writefln("%-25s%s", NameList[i] ~ "(" ~ NameList[j] ~ "(T)):", Qual1!(Qual2!T).stringof);
        }
    }
}

inoutもあるのですが、関数に絡まない形で使われたinoutがどのような挙動になるのか分からないので、今回は除外しました。 結果は、以下のようになりました。


const(const(T)):         const(T)
const(shared(T)):        shared(const(T))
const(immutable(T)):     immutable(T)
shared(const(T)):        shared(const(T))
shared(shared(T)):       shared(T)
shared(immutable(T)):    immutable(T)
immutable(const(T)):     immutable(T)
immutable(shared(T)):    immutable(T)
immutable(immutable(T)): immutable(T)

意味のある型修飾子の組み合わせは、shared(const(T))だけのようです。 よくよく考えると、shared(const(T))は、「共有されている値へのconstなview」なので、たしかに意味があります。 共有されてる値を、絶対に変更しないという条件付きで、見に行ってる、という感じですね。 変更がないのであれば、スレッド間で同期を取る必要もなくなります。

一方、shared(immutable(T))は、immutable(T)になってますが、これは当然と言えば当然ですね。 なぜなら、immutable(T)は不変な値なので、sharedをつけて同期を強制する意味が無いからです。


とりあえず、意味のある型修飾子の組み合わせは、shared(const(T))だけという事が分かりました。

担当:美馬(inoutとはいったい……うごごご!!)