Thread overview
Şablonlarda Tür Uyumsuzluğu
October 23

Merhaba,

Kısaca KT isminde ve tek parametre ile kurulan bir Kendi Türüm (struct) var. Yapı içindeki işleç yüklemeleri (3. kısım) sorunsuz ama dışında şablonları kullanmakta zorluk çekiyorum çünkü kendi türüm :)

Aldığım hata şu şekilde:

>

dmd -O -of"bitOpAllTest" "bitOpAllTest.d" -release -preview=shortenedMethods (/home/pico dizininde)
bitOpAllTest.d(66): Error: none of the overloads of template D main.topla are callable using argument types !()(KendiTürüm!int, int)
bitOpAllTest.d(49): Candidate is: topla(K)
Derleme hatalı.

  1. Sorunu anlayabilmek için enum ile CTFE denedim, bu tamam...
  2. Sonra çalışma zamanı denemek için kendi işlev şablonlarımı oluşturdum ve yasal türler (long, int, short vb.) ile çalışabildiğini gördüm
  3. Kendi Türüm'ün kurulduğu türü (örn. KT4, KT2) taşıyabilemek için de açılmış işlev şablonu içine static if'lerimi yazdıysam da nafile!

Aşağıdaki kodun (yani 2. kısım) tür çıkarsaması yaparak çalıştırmak istiyorum:

  KT4 bir = 1;
  topla(bir, 2).writeln(", ", bir); // Beklenen: "3, 3"

Ama derleme hatası verdiği için açık bir şekilde türü bildirmem gerektiğini farkına vardım. Sanırım 2 parametreli (etkilenen a, etkileyen b) olduğu için tür çıkarsaması olmuyor. Kodun tamamı ve çalışan şekilde aşağıdadır:

/* Lütfen `-preview=shortenedMethods` parametresi ile derleyin,
 * alıştırın kendinizi... :)
 *
 * (Son beta ile default olmak üzere!)
 */
//*
auto toplam(T)(ref T a, T b = 1) => a += b;
auto çarpım(T)(ref T a, T b = 1) => a *= b;
/*/
enum toplam = (int a, int b = 1) => a += b;
enum çarpım = (int a, int b = 1) => a *= b;
//*/
import std.stdio;
void main()
{
// 1. KISIM TAMAM...

  auto Int = int.max;
       Int.toplam;
       assert(Int == int.min);
       assert(is(typeof(Int) == int));

  auto Short = short.max;
       Short.toplam;
       assert(Short == short.min);
       assert(is(typeof(Short) == short));

  auto s = short.max / 2;
       s.writeln; // 16383
       s.çarpım(2).writeln;  // 32766

// 2. SORUNLU KODLAR:

  struct KendiTürüm(T) {
    T n; alias n this;

    this(T n) { this.n = n; }

    ref T opOpAssign(string işleç)(T n)
    if(işleç == "+") => this.n += n;

    ref T opOpAssign(string işleç)(T n)
    if(işleç == "-") => this.n -= n;
  }

  alias KT4 = KendiTürüm!int;
  alias KT2 = KendiTürüm!short;

  template topla(T)
  {
    static if(is(T == int))
    {
      alias T = KT4;

    } else {

      static if(is(T == short))
      {
        alias T = KT2;
      }
    }
    enum topla = (ref T a, int b = 1) => a += b;
  }

  KT4 bir = 1;
  //topla(bir, 2).writeln(", ", bir); /* derlenmiyor!
  topla!int(bir, 2).writeln(", ", bir); //*/

// 3.'Ü DE TAMAM, aksi olamazdı :)
  bir += 1;
  bir.write(", ");

  bir -= 1;
  bir.writeln;

} /*
   2. KISMIN ÇIKTISI: 3, 3

   3. KISMIN ÇIKTISI: 4, 3
*/

Özetle, tüm varyasyonları ile 1 ve 3. kısımlar tamam ama 2. kısımda patladım. Bu konuda bir çözüm önerisi olan var mı?

Teşekkürler...

October 23
On 10/23/22 06:19, Salih Dincer wrote:

> // 2. SORUNLU KODLAR:
>
>    struct KendiTürüm(T) {
>      T n; alias n this;
>
>      this(T n) { this.n = n; }
>
>      ref T opOpAssign(string işleç)(T n)
>      if(işleç == "+") => this.n += n;
>
>      ref T opOpAssign(string işleç)(T n)
>      if(işleç == "-") => this.n -= n;
>    }
>
>    alias KT4 = KendiTürüm!int;
>    alias KT2 = KendiTürüm!short;
>
>    template topla(T)
>    {
>      static if(is(T == int))
>      {
>        alias T = KT4;

T zaten şablon parametresi olarak tanımlanmıştı. Orada şablon parametresini seçmeye mi çalışıyorsun? Seçilemez çünkü içerideki kodlar dışarıda bilinmesi gereken parametreleri belirleyemezler. Şablonlarda parametreler kullanıma göre seçilir (veya açıkça belirtilir).

>      } else {
>
>        static if(is(T == short))
>        {
>          alias T = KT2;
>        }
>      }
>      enum topla = (ref T a, int b = 1) => a += b;
>    }

Yukarıdaki şablon yerine tek şu satır derleniyor:

  enum topla(T)(ref T a, int b = 1) => a += b;

İşe yarıyor mu? Tam olarak ne yapmak istediğini söylersen belki başka çözümleri vardır.

Ali

October 23

On Sunday, 23 October 2022 at 19:08:01 UTC, Ali Çehreli wrote:

>

İşe yarıyor mu? Tam olarak ne yapmak istediğini söylersen belki başka çözümleri vardır.

Varmış hocam; tıkanıp kalınca dışarı çıktım Ikea'da biraz turladım. Geldiğimde, çözüm zihnimde titreşmeye başladı 😀

Sonra kendime şu soruyu sordum, neden bunlar yapının üyesi olmasın...

Hemen tüm yardımcı işlevleri alıp yapı içinde birleştirdim ama henüz derlemem bitmedi; ilk sürüm:

struct Bits(T)
{
  this(T n) { this.n = n; }
  union
  {
    T n;
    ubyte[T.sizeof] bytes;
  }
  alias n this; // Emekli olacak, alter?

  mixin BitOpAll!T;

  string toString() const
  {
    import std.format;
    string result;
    foreach_reverse(i, b; bytes) {
      result ~= b.format!"%08b";
      if(i) result ~= "_";
      else result ~= "\n";
    }
    return result;
  }
}

template BitOpAll(T) //v1.0.2
{
  ref T toggleBit(T n = 0)
    => this.n ^= (T(1) << n);

  ref T setBit(T n = 0)
    => this.n |= (T(1) << n);

  bool isOn(T n = 0)
    => this.n & (T(1) << n) ? true : false;

  ref T clearBit(T n = 0)
    => this.n &= ~(T(1) << n);

  auto setAll(T n = 7)
    => this.n = cast(T)((1 << n) - 1);

  T lowBitValue()
    => this.n & (-this.n);

  T shiftUntilOne()
  {
    T result, t = this.n;
    //result = imported!"core.bitop".bsf(this.n);/*
    while(t > 1) {
      result++;
      t >>>= 1;
    }
    return result;
  }
  unittest
  {
    assert(shiftUntilZero(64) == 6);
    assert(shiftUntilZero(58) == 5);
    assert(shiftUntilZero(32) == 5);
    assert(shiftUntilZero(16) == 4);
    assert(shiftUntilZero(10) == 3);
  }
}
October 23

On Sunday, 23 October 2022 at 22:14:18 UTC, Salih Dincer wrote:

>

Hemen tüm yardımcı işlevleri alıp yapı içinde birleştirdim ama henüz derlemem bitmedi; ilk sürüm:

Pardon, test kodunu ve yardımcı birkaç şeyi unutmuşum. Kodun diğer yarısı aşağıda, teşekkürler...

import std.stdio;

void main()
{
  // #.lowBitValue(default n = 0): get(T)
  Bit4[] testData = [
    Bit4(1), Bit4(3), Bit4(5), Bit4(9),    // hepsi 1
    Bit4(2), Bit4(6), Bit4(10), Bit4(18),  // hepsi 2
    Bit4(12), Bit4(20), Bit4(36), Bit4(68),// hepsi 4
  ];

  auto hepsiBir = testData[0..4];
  auto hepsiİki = testData[4..8];
  auto hepsiDört = testData[8..12];

  foreach(i; 0..4) {
    assert(hepsiBir[i].lowBitValue == 1);
    assert(hepsiİki[i].lowBitValue == 2);
    assert(hepsiDört[i].lowBitValue == 4);
  }

  Bit4 tInt = 41;

  // #.isOn(default n = 0): get(bool)
  assert(tInt.isOn(5));
  assert(tInt.setBit(1) == 43);

  tInt.writeln; // ..._00101011
  assert(tInt.toggleBit(1) == 41);

  tInt = uint.max;
  tInt.writeln; // ..._11111111

  // #.clearBit(default n = 0): set&get(ref)
  assert(tInt.clearBit(31) == int.max);
  assert(tInt == int.max);
  assert(tInt.clearBit(31) == int.max);

  tInt = 0;
  // #.setAll(default n = 7): set&get(ref)
  assert(tInt.setAll(15) == short.max);
  assert(tInt.setAll == byte.max);

  // #.shiftUntilOne(): get(T)
  Bit1 a, b;
  a = 58;
  b = 32;
  assert(a.shiftUntilOne == a.shiftUntilOne);
}

 alias Bit8 = Bits!ulong;
 alias Bit4 = Bits!uint;
 alias Bit2 = Bits!ushort;
struct Bit1
{
  ubyte n; alias n this;

  mixin BitOpAll!ubyte;

  string toString() const
  {
    import std.format;
    return n.format!"%08b\n";
  }
}