【问题标题】:c++ template parameter is ambiguousc++模板参数不明确
【发布时间】:2012-01-25 08:31:56
【问题描述】:

我正在尝试实现三个函数并且有很多错误,所有这些错误都具有相同的签名:

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;

【问题讨论】:

  • BlendVividLightf 中的 T 是什么类型。请显示此函数的调用。
  • _p1.r_p2.r 的类型是 double 吗?如果不是,则会导致编译错误。
  • _p1.r 和 _p2.r 是浮动的。为什么会导致问题?

标签: c++ templates compiler-errors type-mismatch


【解决方案1】:

问题是当你调用ColorBurnColorDodge时,模板参数之一是float,另一个是double:

ColorBurn(base, (2.0 * blend))

这里,base 是浮点数,而表达式2.0 * blend 是双精度(因为2.0 是双精度常数,所以整个表达式变成双精度)。

现在,编译器无法决定是将 ColorBurn 实例化为 float 还是 double。

要解决此问题,请将您的常量更改为单精度浮点常量(这很可能是您想要的):

ColorBurn(base, (2.0f * blend))

ColorDodge 也是如此。

请注意,如果您尝试将 BlendVividLightf 实例化为浮点以外的其他内容,您仍然会遇到麻烦——您的函数以太多方式假设您正在处理浮点值,因此您必须如果您希望它们适用于其他参数类型,请引入一些类型转换。

【讨论】:

  • 解决方法是使用static_cast&lt;T&gt;(2.0)。或者使用命名常量:static T const doubler = 2.0;。无论哪种方式,您都强制常量具有所需的类型。
  • @James:或者,作为一个小调整,static_cast&lt;T&gt;(2)(强调这仅适用于整数常量)
  • 如果我正确理解他的代码,它只适用于浮点类型。
  • @James:在目前的状态下,是的——但我假设他最终可能想让它也适用于整数类型......
【解决方案2】:

问题的原因是0.5 是一个double-literal,而T0 是一个浮点数。因此,您向模板传递了两个不同类型的参数,因此编译器无法决定使用哪一个。有两种解决方案:

  1. 0.5 更改为 0.5f 以使其成为 float-literal。
  2. 为您的模板提供明确的类型参数,如下所示:

    ColorBurn<float>(base, (2.0 * blend))
    

【讨论】:

    【解决方案3】:

    也许您必须将 (2.0 * blend) 的结果转换为“T”并将其传递给 ColorBurn... 例如:

    ColorBurn(base, static_cast<T>(2.0 * blend));
    

    【讨论】:

      【解决方案4】:

      我可以猜到,问题是由于floatdouble 不匹配造成的。您在所有 3 个函数中都创建(强制)template 相同类型的 T0/T1/T 参数。因此,当您使用float 调用该函数时,它会出现问题。请在此处查看demo

      这可以通过将您的pixel_t 成员设置为double 而不是float 来解决。

      【讨论】:

        【解决方案5】:

        你的问题出在这一行:

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

        此处文字 2.0 将强制将第二个参数转换为 double ,但是由于第一个参数是其原始模板类型,并且在您的代码中稍后是 float,编译器无法推断您是否打算调用 @ 987654324@ 或 ColorBurn&lt;float&gt;(同样适用于本行后面对 ColorDodge 的调用)。

        您可以通过以下任一方式修复错误:

        • 在函数调用中明确告诉编译器模板参数
        • 也强制转换为第一个参数的两倍,例如... * 1.0
        • 将第二个参数中的双精度字面值更改为浮点字面值,例如... * 2.0f
        • 为 float 和 double 编写专门化或单独的重载,并在上面进行适当的更改以确保两个参数的类型相同

        【讨论】:

          猜你喜欢
          • 2017-03-22
          • 2015-11-10
          • 1970-01-01
          • 2015-01-16
          • 1970-01-01
          • 2012-01-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多