Вопрос

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;
Это было полезно?

Решение

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.

Другие советы

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:

  1. Change 0.5 to 0.5f to make it a float-literal.
  2. 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top