Ok, I read throught quite some “could not deduce template argument” questions but none seems to match my case — or I don't understand the answer…
There's one that I feel goes in the right direction, but I failed extracting the solution for my problem.
The stripped down code in my header looks like this:
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 instantiate it like this:
unsigned char pixels[] = {23, 42, 65, 97};
TemplateProblem<int> tp(pixels, 4);
From VS2012 I get these messages:
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 error also occurs when I move the two struct
s out of the class
as this answer suggests.
The compiler error is not very helpful in indicating the actual problem.
The actual problem is that you pass UnaryFunction<Tin, T>
by value to your Init
function (and one of the constructors), but all instantiations of UnaryFunction<>
result in an abstract class (which can not be passed by value).
The easy solution is to use pass-by-reference for UnaryFunction
, so that mapper
refers to the actual object passed in.
The typical solution in the STL for passing functors is to use a separate template argument, like this:
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;
}
}
Then you don't need the UnaryFunctionL<>
base class. If an incompatible mapper
is passed, this will be diagnosed when it is used in the body of the function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With