3

Ubuntu 13.04 64 ビットで DMD64 D コンパイラ v2.063.2 を使用しています。

私は以下のようにクラスを書きました:

class FixedList(T){
    // list
    private T[] list;

    // number of items
    private size_t numberOfItems;

    // capacity
    private size_t capacity;

    // mutex
    private Mutex listMutex;

    // get capacity
    @property public size_t Capacity(){ return capacity; }
    @property public shared size_t Capacity(){ return capacity; }

    // constructor
    public this( size_t capacity ){
        // initialise
        numberOfItems = 0;
        this.capacity = capacity;

        writeln("Cons Normal");
    }

    // constructor
    public shared this( size_t capacity ){
        // initialise
        numberOfItems = 0;
        this.capacity = capacity;

        // create mutex
        listMutex = cast(shared)(new Mutex());

        writeln("Cons Shared");
    }
}

クラスはこのように書かれていますが、メイン関数では、そのコードを書きました:

auto list1 = new shared FixedList!int( 128 );
auto list2 = new FixedList!int( 128 );

これで出力すると、エラーはまったくなく、出力は次のようになります。

Cons Shared
Cons Normal

次にwriteln、コードから両方の行を削除します。コードを再コンパイルすると、次のようなエラー メッセージが表示されるようになります。

src/webapp.d(61): Error: constructor lists.FixedList!(int).FixedList.this called with argument types:
    ((int) shared)
matches both:
    lists.d(28): lists.FixedList!(int).FixedList.this(ulong capacity)
and:
    lists.d(37): lists.FixedList!(int).FixedList.this(ulong capacity)
src/app.d(61): Error: no constructor for FixedList
src/app.d(62): Error: constructor lists.FixedList!(int).FixedList.this called with argument types:
    ((int))
matches both:
    lists.d(28): lists.FixedList!(int).FixedList.this(ulong capacity)
and:
    lists.d(37): lists.FixedList!(int).FixedList.this(ulong capacity)
src/app.d(62): Error: no constructor for FixedList
make: *** [all] Error 1

基本的にwriteln関数はエラーを防止しています。実際writelnには多くの場所で防止されていますが、なぜこれが起こっているのかわかりません.

32ビット用のフラグを付けてコードをコンパイルしようとしましたm32が、それでも同じです。私は何か間違ったことをしていますか、それともこれはバグですか?

4

2 に答える 2

3

purenothrow、および@safeは、テンプレート関数に対して推論されます。テンプレート化されているように、そのFixedListコンストラクターはテンプレート化されています。I/O とは異なりwritelnます (また、そうではありません) 。pureそのため、writelnis がコンストラクター内にある場合、それらは ではないと推測されpureますが、コンストラクターが行っている他のすべてのことはpureであるため、 への呼び出しがなければwriteln、それらは になりpureます。

状況によっては、コンパイラは関数の戻り値の型を変更して暗黙的にorpureに変換することができます。これが機能するのは、そのような場合、返されるものが新しい一意のオブジェクトであり、それを型システムにキャストすること、または型システムに違反しないことをコンパイラが認識しているためです。パラメータの型は、戻り値が一意であることをコンパイラが保証できるかどうかに影響を与える可能性があるため、すべての関数が適格であるとは限りませんが、多くの関数はこれを利用して戻り値を暗黙的にorに変換できます。これは、コードの重複 (異なる戻り値の型の場合)またはコピーを回避できるため、便利です。immutablesharedimmutablesharedpurepureimmutablesharedimmutablesharedであり、他の場所で参照されていないことを保証することはできません。コピーして、必要な型を取得する必要があります。この場合、コンパイラは、オブジェクトが他の場所で参照されていないことを保証できるため、安全にキャストできます。

コンストラクターは効果的に新しい値を返すため、この機能の影響を受ける可能性があります。これにより、コンストラクターが である場合、コンストラクターを複製する必要なく (そうでない場合に行う必要があるように) pure、多くの場合、コンストラクターから値を作成できimmutableます。他の関数と同様に、これが機能するかどうかはコンストラクターのパラメーターの型によって異なりますが、多くの場合可能であり、コードの重複を避けるのに役立ちます。sharedpurepure

問題を引き起こしているのは、FixedListのコンストラクターが both のpure場合、コンパイラーはそれらのいずれかを使用してsharedオブジェクトを構築できることです。そのため、どれを選択すればよいかわからず、あいまいなエラーが発生します。

これは、コンパイラはおそらく明示的に としてマークされているコンストラクタを優先するはずであるという理論のバグとして報告しましたが、コンパイラ開発shared者が何を決定するかはわかりません。関数からの戻り値を暗黙的に変換するpure機能はかなり新しい機能であり、これらの暗黙的な変換を行うことができる場合とできない場合についてはまだ調査中であり、予期しない問題 (おそらくこのような問題) とコンパイラの両方が発生する可能性があります。バグ (たとえば、少なくとも 1 つのケースがimmutableあり、現在、変換すべきではないときに変換を行っています)。ただし、これらの問題はかなり迅速に解決されると確信しています。

于 2013-07-16T20:16:55.083 に答える