Yıldıray

Yeni üye
12 Kas 2015
10
1
0
(42) Konya
Oluşturduğum bir struct yapısını array olarak store etmek için TArray<> yapısını kullandığımda "RemoveSingle, Remove, Find" metodlardan hangisini kullandıysam derleme hatası alıyorum. Ancak "Add, Num" gibi metodlarda sorun olmuyor.

HATA:
Error 4 error C2678: binary '==' : no operator found which takes a left-hand operand of type 'const FLaserData' (or there is no acceptable conversion) C:\Program Files\Epic Games\4.9\Engine\Source\Runtime\Core\Public\Containers\Array.h 868

Struct yapısı:
Kod:
USTRUCT(BlueprintType)
struct FLaserData : public FTableRowBase
{
	GENERATED_USTRUCT_BODY()

public:
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Laser) FString Name;
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Laser) TAssetPtr<UTexture> Image;
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Laser) float Cost;
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Laser) int32 Level;
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Laser) float PhysicleDamage;
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Laser) float ShieldDamage;
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Laser) float ConsumeEnergy;

public:
	FLaserData()
	{
		Cost = 0.0f;
		Level = 0;
		PhysicleDamage = 0.0f;
		ShieldDamage = 0.0f;
		ConsumeEnergy = 0.0f;
		Name = TEXT("Default");
	}
};

Dizi Referansı
Kod:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Weapon) TArray<FLaserData> Lasers;
 
Bunun için öncelikle "value" ve "reference" arasındaki farkı irdeleyelim.

"value" adından da anlaşılacağı gibi her zaman değer oluşturmak, veri depolama gibi amaçlarla kullanılır. "reference" ise mevcut bir verinin, nesnenin yada herhangi bir tipin bellekteki alanını gösterir. Aşağıdaki örneklere bakalım.

Kod:
int32 a = 5;
int32 b = a;
Yukarıdaki örnekte bellekte, '5' değerinde, 4 byte'lık bir yer ayrıldı. Ardından bir 4 byte'lık yer daha ayrıldı ve '5' değerini aldı. Toplamda 8 bytelık bir yer işgal edildi. 'a' ve 'b'nin birbiriyle tek ilişkisi aynı değere sahip olması. Burada değer özel isimler gibi düşünülebilir. Ahmet isimli 2 kişiyi ele alalım, bunlar aynı isimlere sahipler ama aynı kişi değiller.  Yine de kıyaslandıklarında temel tipler(char, int, float, double, bool...vb) olduklarından eşit olduğu sonucuna ulaşılır.
Kod:
if (a == b) // a == b, true değer döndürür
{
  // Burası çalışır.
}
Ancak bunlar temel tipler olmasaydı, eşitlik kıyaslamasını tanımlamamız gerekirdi. Tıpkı aşağıdaki gibi:
Kod:
struct FooStruct
{
  int Bar;
}
FooStruct s1;
s1.Deger = 10;
FooStruct s2;
s2.Deger = 10;

if (s1 == s2) // Compile Time Error!!!
{
  // Burası çalışmaz, zaten derleme hatası aldık
}

İşte aldığın hata buradan kaynaklanmaktadır. "TArray" ve diğer bütün "Container"lar, "Find" işlemi yani belirtilen veriyi bulma işlemi yaparken; en basitinden, verilen değer ile dizideki elemanlar arasında en baştan sona doğru tüm elemanlar için eşitlik kıyaslaması yaparlar. Dolayısı ile "TArray" "generic" sınıfı, bu kıyaslamayı yapmak üzere tanımlandığından aynı derleme hatasını alıyorsun.

Ne yapmalı?
1. "Operator Overloading" denilen yöntemle, tip üzerinde "==" işleminin ne anlama geldiğini derleyiciye anlatmak gerekir.

Kod:
struct FooStruct
{
  int Bar;

  bool operator== (const FooStruct& other) const
  {
    return Bar == other.Bar;
  }
}
FooStruct s1;
s1.Deger = 10;
FooStruct s2;
s2.Deger = 10;

if (s1 == s2) // Derleme hatası yok
{
  // Burası da çalışır çünkü "s1.Bar = s2.Bar"
}

2. "Value" yerine doğrudan "reference" kullanılabilir. "Reference", bellek adresini işaret ettiğinden, üzerlerinde daima eşitlik kıyaslaması yapılabilir, tanıtmaya gerek yoktur.

Ancak bu durumda belli ki "Item Database" oluşturuyorsun. Bu yüzden ilk yöntemi kullanmalısın. Yapman gereken basitçe aşağıdaki methodu "FLaserData"ya eklemek. Eşitlik kıyaslamasının neye göre yapacağına sen karar vermelisin. Bu bir veritabanı mantığı kullandığından, verilerin "Id" gibi benzersiz bir değişkeni olmasını tavsiye ederim. Zaten bu "struct, FTableRowBase" olduğundan bu yapıya uygun, yine de "Name" değişkenin benzersiz olacaksa, onda da kıyaslama yapabilirsin.
Kod:
FORCEINLINE bool operator== (const FLaserData& other) const
{
  return Name == other.Name;
}
Böylece derleyici, "FLaserData" "value" tipi için; eşitliğin, isimlerin(Name) eşit olması anlamına geldiğini biliyor.
 
Dediklerinizi aynen uyguladım ve sorunsuz çalıştı. Çok teşekkür ederim. Karşılaştırma işlemini Name'e göre yaptım database kısmında sizinde söylediğiniz gibi FTableRowBase'e göre uyarladım. Kendisine ait bir benzersiz değer bulunduruyor.

Ayrıca Struct yapıları hakkında bilgi sahibi oldum. Bu çok işime yarayacak. Teşekkürler.
 
Yıldıray' Alıntı:
Dediklerinizi aynen uyguladım ve sorunsuz çalıştı. Çok teşekkür ederim. Karşılaştırma işlemini Name'e göre yaptım database kısmında sizinde söylediğiniz gibi FTableRowBase'e göre uyarladım. Kendisine ait bir benzersiz değer bulunduruyor.

Ayrıca Struct yapıları hakkında bilgi sahibi oldum. Bu çok işime yarayacak. Teşekkürler.

Asıl C++ forumunun ilk sorusunu sorduğun için ben teşekkür ederim ;)

Bu arada örnek kodlarda üye isimlerini "Bar" olarak tanımlayıp "Değer" diye çağırmışım; elbette onların hepsi "Bar" olacaktı ama düzeltmiyorum.