параметр шаблона c ++ неоднозначен - PullRequest
1 голос
/ 25 января 2012

Я пытаюсь реализовать три функции и у меня много ошибок, каждая из которых имеет одинаковую подпись:

error C2782: 'T0 ColorBurn(T0,T0)' : template parameter 'T0' is ambiguous
error C2782: 'T1 ColorDodge(T1,T1)' : template parameter 'T1' is ambiguous

Где я допустил ошибку?
Это мой код:

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)));
}

пример вызова 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;

Ответы [ 5 ]

9 голосов
/ 25 января 2012

Проблема в том, что когда вы вызываете ColorBurn и ColorDodge, один из аргументов шаблона является плавающим, а другой - двойным:

ColorBurn(base, (2.0 * blend))

Здесь base является плавающим, а выражение 2.0 * blend является двойной (потому что 2.0 является двойной константой, поэтому все выражение становится двойным).

Теперь компилятор не может решить, создавать ли экземпляр ColorBurn для floatили для double.

Чтобы исправить это, измените ваши константы на константы с плавающей точкой одинарной точности (что, скорее всего, вам и нужно):

ColorBurn(base, (2.0f * blend))

И аналогично для ColorDodge.

Обратите внимание, что у вас все еще будут проблемы, если вы попытаетесь создать экземпляр BlendVividLightf для чего-то, кроме float - ваши функции слишком часто предполагают, что вы имеете дело со значениями с плавающей запятой, поэтому вы будетенеобходимо ввести некоторые преобразования типов, если вы хотите, чтобы они работали для других типов аргументов.

3 голосов
/ 25 января 2012

Причина проблемы в том, что 0.5 является double -литералом, а T0 является плавающей точкой. Таким образом, вы передаете шаблону два параметра с разными типами, и, таким образом, компилятор не может решить, какой из них использовать. Есть два решения:

  1. Измените 0.5 на 0.5f, чтобы сделать его float -литеральным.
  2. Предоставьте явные параметры типа вашим шаблонам, например:

    ColorBurn<float>(base, (2.0 * blend))
    
2 голосов
/ 25 января 2012

Может быть, вам нужно привести результат (2.0 * blend) к "T" и передать его в ColorBurn ... Например:

ColorBurn(base, static_cast<T>(2.0 * blend));
1 голос
/ 25 января 2012

Ваша проблема в этой строке:

ColorBurn(base, (2.0 * blend)) ...

Здесь литерал 2.0 принудительно преобразует второй параметр в double, однако, поскольку первый параметр является его исходным типом шаблона, а в вашем коде позже он float, компилятор не может определить, хотели ли вы вызвать ColorBurn<double> или ColorBurn<float> (то же самое относится к вызову ColorDodge позже в этой строке).

Вы можете исправить ошибку одним из следующих способов:

  • явно указывает компилятору параметр шаблона в вызове функции
  • принудительное преобразование в удвоение первого параметра, например, ... * 1.0
  • замена двойных литералов во втором параметре на плавающие литералы, например ... * 2.0f
  • написание специализации или отдельных перегрузок для float и double и внесение соответствующих изменений выше, чтобы гарантировать, что оба параметра имеют одинаковый тип
1 голос
/ 25 января 2012

Могу предположить, что проблема связана с несовпадением float и double. Вы делаете (форсируете) оба template аргумента одного типа T0/T1/T во всех 3 функциях. Поэтому, когда вы вызываете функцию, используя float, у нее будут проблемы. Смотрите демо здесь.

Эту проблему можно решить, указав для pixel_t членов значение double вместо float.

.
...