c++ template parameter is ambiguous
-
19-04-2021 - |
Pergunta
I am trying to implement three functions and have a lot of errors all of which have the same signature:
error C2782: 'T0 ColorBurn(T0,T0)' : template parameter 'T0' is ambiguous
error C2782: 'T1 ColorDodge(T1,T1)' : template parameter 'T1' is ambiguous
Where I have make a mistake?
This is my code:
template <class T0>
T0 ColorBurn(T0 base, T0 blend)
{
return (blend == 0.0) ? blend : std::max((1.0 - ((1.0 - base) / blend)), 0.0);
}
template <class T1>
T1 ColorDodge(T1 base, T1 blend)
{
return (blend == 1.0) ? blend : std::min(base / (1.0 - blend), 1.0);
}
template <class T>
T BlendVividLightf(T base, T blend)
{
return (blend < 0.5) ? ColorBurn(base, (2.0 * blend)) : ColorDodge(base, (2.0 * (blend - 0.5)));
}
the sample of calling BlendVividLightf:
static pixel_t blend_vivid_light(pixel_t _p1, pixel_t _p2)
{
pixel_t po;
po.r = BlendVividLightf(_p1.r, _p2.r);
....
}
pixel_t - is my struct for rgb values:
typedef struct
{
float r;
float g;
float b;
} pixel_t;
Solução
I can guess, that the problem is due to mismatch of float
and double
. You are making (forcing) both template
arguments of same type T0/T1/T
in all the 3 functions. So when you call the function using float
it will have problem. See the demo here.
This can be solved by making your pixel_t
members as double
instead of float
.
Outras dicas
The problem is that when you call ColorBurn
and ColorDodge
, one of the template arguments is a float and the other is a double:
ColorBurn(base, (2.0 * blend))
Here, base
is a float, and the expression 2.0 * blend
is a double (because 2.0
is a double constant, so the whole expression becomes double).
Now, the compiler can't decide whether to instantiate ColorBurn
for float or for double.
To fix this, change your constants to single-precision float constants (which is likely what you want anyway):
ColorBurn(base, (2.0f * blend))
And similarly for ColorDodge
.
Note that you'll still have trouble if you try to instantiate BlendVividLightf
for something other than float -- your functions assume in too many ways that you're dealing with floating-point values, so you'll have to introduce some type conversions if you want them to work for other argument types.
The cause of the problem is that 0.5
is a double
-literal, and T0
is a float. So you are passing the template two parameters with different types, and thus the compiler cannot decide which one to use. There are two solution:
- Change
0.5
to0.5f
to make it afloat
-literal. Provide explicit type-parameters to your templates, like so:
ColorBurn<float>(base, (2.0 * blend))
Maybe you have to cast the result of (2.0 * blend) to "T" and pass it to ColorBurn... For instance:
ColorBurn(base, static_cast<T>(2.0 * blend));
Your problem is in this line:
ColorBurn(base, (2.0 * blend)) ...
Here literal 2.0 will force conversion of second parameter to double
, however since first parameter is its original template type, and in your code later on it's float
, the compiler is unable to deduce whether you meant to call ColorBurn<double>
or ColorBurn<float>
(same applies to call to ColorDodge
later in this line).
You can fix the error by either of:
- telling the compiler explicitly template parameter in the function call
- forcing conversion to double of the first parameter too e.g.
... * 1.0
- changing double literals in the second parameter to float literals e.g.
... * 2.0f
- writing specialisation, or separate overloads, for float and double and making appropriate changes above to ensure both parameters are same type