PDA

Tam Sürümünü Görmek İçin : Template hatası


depones
23/11/2007, 11:11
Merhaba,

GoF'un Strategy tasarım kalıbını C++'ta implemente etmeyi denedim. Farklı sıralama algoritmalarını kapsülleyerek kullanıcı kodun çalışma zamanında istediği algoritmayı seçmesini sağlayacak bir yapı kurmaya çalıştım.

Projemi build ettiğimde;

Error 1 error C2664: 'Context<T,size>::Context(SortStrategy<int (void),10> *)' : cannot convert parameter 1 from 'InsertionSort<T,size> *' to 'SortStrategy<T,size> *' c:\documents and settings\lambert\desktop\sortstrategy\sortstrategy \main.cpp 11


hata mesajını alıyorum.

Şimdi, yazdığım kodu göndereceğim. Kod biraz uzun. Böyle durumlarda kodu mesaja mı gömmeli yoksa .txt dosyası olarak mı göndermeli, nasıl daha uygun olacağını da belirtirseniz memnun olurum.


SortStrategy.hpp:

template <typename T, int size>
class SortStrategy {

public:
virtual void Sort(T *source) = 0;

};



/* Explicit specialization */

template <typename T, int size>
class SortStrategy<T *, size> {

public:
virtual void Sort(T *source) = 0;

};


SelectionSort.hpp

template <typename T, int size>
class SelectionSort : public SortStrategy<T, size> {

public:
virtual void Sort(T *source)
{
for (int i = 0; i < size; ++i) {
T min = source[i];
T minIndex = i;

for (int j = i + 1; j < size; ++j)
if (min > source[j]) {
min = source[j];
minIndex = j;
}
source[minIndex] = source[i];
source[i] = min;
}
}

};



/* Explicit specialization */

template <typename T, int size>
class SelectionSort<T *, size> : public SortStrategy<T *, size> {

public:
virtual void Sort(T *source)
{
for (int i = 0; i < size; ++i) {
T min = source[i];
T minIndex = i;

for (int j = i + 1; j < size; ++j)
if (min > source[j]) {
min = source[j];
minIndex = j;
}
source[minIndex] = source[i];
source[i] = min;
}
}

};


InsertionSort.hpp

template <typename T, int size>
class InsertionSort : public SortStrategy<T, size> {

public:
virtual void Sort(T *source)
{
int j;

for (int i = 1; i < size; ++i) {
T temp = source[i];

for (j = i; j > 0 && source[j - 1] > temp; --j)
source[j] = source[j - 1];
source[j] = temp;
}
}

};


/* Explicit specialization */

template <typename T, int size>
class InsertionSort<T *, size> : public SortStrategy<T *, size> {

public:
virtual void Sort(T *source)
{
int j;

for (int i = 1; i < size; ++i) {
T temp = source[i];

for (j = i; j > 0 && source[j - 1] > temp; --j)
source[j] = source[j - 1];
source[j] = temp;
}
}

};


Context.hpp

#include "SortStrategy.hpp"
#include "BubbleSort.hpp"
#include "SelectionSort.hpp"
#include "InsertionSort.hpp"

template <typename T, int size>
class Context {
SortStrategy<T(), size> *mStrategy;

public:
Context(SortStrategy<T(), size> *strategy)
{
this->mStrategy = strategy;
}

void Sort()
{
this->mStrategy->Sort(T());
}

};



/* Explicit specialization */

template <typename T, int size>
class Context<T *, size> {
SortStrategy<T(), size> *mStrategy;

public:
Context(SortStrategy<T(), size> *strategy)
{
this->mStrategy = strategy;
}

void Sort()
{
this->mStrategy->Sort(T());
}

};


main.cpp

#include <iostream>
#include "Context.hpp"

using namespace std;


int main()
{
int a[10] = {15, 12, 1, 4, 88, 3, 67, 89, 1, 88};

Context<int *, 10> *con = new Context<int *, 10>(new InsertionSort<int *, 10>());

return 0;
}


Hatanın, template'lerin yanlış kullanılmasından kaynaklanmış olabileceğini düşünüyorum, ancak tespit edemedim. Birinci sorum, hata nerede ?
Buna ek olarak, template'lerle ilgili explicit specification yaparken her <T> türünden template sınıf için yukarıda benim de yaptığım gibi aynı sınıfın <T *> türünden bir bildirimini daha yapmak gerekir mi ?
Bir diğer soru da, <T *> türünden yapılan bildirimde türetme sentaksında da <T *> yapılmalı mı ? Bu son yazdığım açık olmadı, örneklendireyim:

InsertionSort'un specification'ında şöyle yazdım:

class InsertionSort<T *, size> : public SortStrategy<T *, size> {

Burada koyu yaptığım yer <T> türünden sınıf bildirimi için <T> iken specification'da <T *> türünden sınıf bildirimi için <T *> mı yapılmalı ?

İlgileceklere şimdiden teşekkür ederim :)


acehreli
23/11/2007, 20:30
1) Sablonlarin isaretciler icin ayri ayri yazilmalari dogru degil. Gerekirse yapilir tabii ama seninki gibi siralama isleminde zaten sen hep isaretcilerle calisiyorsun. Sablon parametresi olarak T verildiginde sen T* kullaniyorsun zaten. Butun isaretci "specialization"larini gonul rahatligiyla sil. :)

Zaten ayni kodun iki kere yer almasi bir yerlerde bir yanlislik oldugunun isaretidir.


2) Siralanacak seylerin sayisinin sablon parametresi olmasi cok kisitlayici, cunku bu sayiyi derleme zamaninda biliyor olmalisin. Bunu herhalde sonradan degistireceksin zaten.

Yine de, Context'in ve SortStrategy'nin 'size'dan haberinin olmasina gerek yok. Sort'a da neyi siralayacagini soyleyince Context su hale geliyor:


template <typename T>
class Context {
SortStrategy<T> *mStrategy;

public:
Context(SortStrategy<T> *strategy)
{
this->mStrategy = strategy;
}

void Sort(T * a)
{
this->mStrategy->Sort(a);
}

};


Not: Iki noktada T yerine T() kullanmistin. Onlari da yukarida duzelttim.


Sonradan SortStrategy::Sort'un 'size' almasini istersin:

void Sort(T * a, size_t size);

veya stardartta oldugu gibi iki isaretci:

void Sort(T * bas, T * son);


3) g++, SortStrategy'nin bozucusunun 'virtual' olmasi gerektigini hatirlatti:

virtual ~SortStrategy()
{}


4) main'in icinde sablon parametresi olarak int* degil, int kullanmalisin; cunku isaretciler yoluyla islem yapildigi zaten Sort islevlerinde belli:

Context<int, 10> *con = new Context<int, 10>(new InsertionSort<int, 10>());

Not: Yukarida yazdigim Context'ten 'size'i cikartmistim ama bu satirda hAlA var. Onemli olan, int* yerine int kullaniyorum.

Ali

depones
24/11/2007, 00:42
Cevabın için teşekkür ederim acehreli :)