2012-12-19 9 views
5

Ok, czytam throught sporo „nie można wywnioskować szablon argumentów” pytania, ale nikt zdaje się pasować do mojej sprawy - albo ja nie rozumiem odpowiedź ...Wydedukowania szablon argumentem dla zagnieżdżonego szablonu nie

Jest one że czuć idzie w dobrym kierunku, ale nie udało mi się wyodrębnić rozwiązania dla mojego problemu.

okrojona kod w moim nagłówka wygląda następująco:

template<typename T> 
class TemplateProblem 
{ 
public: 
    // Do I really need this or did I miss something from the STL? 
    template<typename Tin, typename Tout> 
    struct UnaryFunction : public std::unary_function<Tin, Tout> 
    { 
     virtual Tout operator()(Tin input) = 0; 
    }; 

    template<typename Tin, typename Tout> 
    struct StaticCast : public UnaryFunction<Tin, Tout> 
    { 
     virtual Tout operator()(Tin input) 
     { 
      return static_cast<Tout>(input); 
     } 
    }; 

private: 
    T * const _data; 
    T const _bias; 

    template<typename Tin> 
    void Init(Tin * data, int length, UnaryFunction<Tin, T> mapper, Tin bias); 

public: 
    template<typename Tin> 
    TemplateProblem(Tin * data, int length, Tin bias = Tin()); 

    template<typename Tin> 
    TemplateProblem(Tin * data, int length, UnaryFunction<Tin, T> mapper, Tin bias = T()); 
}; 

template<typename T> 
template<typename Tin> 
void TemplateProblem<T>::Init(Tin * data, int length, UnaryFunction<Tin, T> mapper, Tin bias) 
{ 
    T mappedBias = mapper(bias); 
    for (int i = 0; i < length; i++) 
    { 
     _data[i] = data[i] + mappedBias; 
    } 
} 

template<typename T> 
template<typename Tin> 
TemplateProblem<T>::TemplateProblem(Tin * data, int length, UnaryFunction<Tin, T> mapper, Tin bias = T()) 
    : _data(new T[length]), _bias(bias) 
{ 
    Init(data, length, mapper, bias); 
} 

template<typename T> 
template<typename Tin> 
TemplateProblem<T>::TemplateProblem(Tin * data, int length, Tin bias = T()) 
    : _data(new T[length]), _bias(bias) 
{ 
    StaticCast<Tin, T> cast; 
    Init(data, length, cast, bias); 
} 

I instancji to tak:

unsigned char pixels[] = {23, 42, 65, 97}; 
TemplateProblem<int> tp(pixels, 4); 

Od VS2012 otrzymuję te wiadomości:

Error 1 error C2784: 'void TemplateProblem<T>::Init(Tin *,int,TemplateProblem<T>::UnaryFunction<Tin,T>,Tin)' : could not deduce template argument for 'TemplateProblem<T>::UnaryFunction<Tin,T>' from 'TemplateProblem<T>::StaticCast<Tin,Tout>' ...\templateproblem.h 62 1 TemplateProblem 
Error 2 error C2893: Failed to specialize function template 'void TemplateProblem<T>::Init(Tin *,int,TemplateProblem<T>::UnaryFunction<Tin,T>,Tin)' ...\templateproblem.h 62 1 TemplateProblem 

The błąd występuje również, gdy przesuniemy dwa struct s z jakoSugeruje.

+1

Kod wystąpienia i komunikaty o błędach są całkowicie niezwiązane. Błąd mówi o 'StaticCast ', ale nie masz go nigdzie w swoim kodzie instancji. – Xeo

+0

http://liveworkspace.org/code/4psoUf$0 kompiluje dobrze ... Twój kod (przed poprawkami) nie był kompilowany. – ForEveR

+0

@Xeo: StaticCast używa 3 linii od dołu. – primfaktor

Odpowiedz

4

Błąd kompilatora nie jest bardzo pomocny w wskazywaniu rzeczywistego problemu.

Rzeczywista problemem jest to, że można przejść przez wartość UnaryFunction<Tin, T> do Init funkcji (i jeden z konstruktorów), ale wszystkie dawałaby o UnaryFunction<> spowodować klasy abstrakcyjnej (które nie mogą być przekazywane przez wartość). Proste rozwiązanie jest wykorzystanie przejść przez odwołanie do UnaryFunction tak, mapper odnosi się do rzeczywistego obiektu przechodzi w

Typowym rozwiązaniem STL przekazywania funktory jest użycie oddzielnego szablonu argumentu tak.:

template<typename T> 
template<typename Tin, Tmapper> 
void TemplateProblem<T>::Init(Tin * data, int length, Tmapper mapper, Tin bias) 
{ 
    T mappedBias = mapper(bias); 
    for (int i = 0; i < length; i++) 
    { 
     _data[i] = data[i] + mappedBias; 
    } 
} 

Wtedy nie potrzebujesz klasy bazowej UnaryFunctionL<>. Jeśli zostanie przekazany niekompatybilny mapper, zostanie to zdiagnozowane, gdy zostanie użyte w ciele funkcji.

+0

Ten argument szablonu 'Tmapper' działa * i * ułatwia życie. Wielkie dzięki! – primfaktor

Powiązane problemy