【问题标题】:Is it legal to overload a function template with another function template?用另一个函数模板重载一个函数模板是否合法?
【发布时间】:2014-02-10 12:48:29
【问题描述】:

我正在尝试创建一个重载方法,其中两者都是模板化的。一个需要 4 个参数,一个需要 5 个参数。但是我得到一个错误,类似于

Error C2780 ... OutOfPlaceReturn ... : expects 4 arguments - 5 provided.

... A bunch of template parameters ...

See declaration of ' ... ::OutOfPlaceReturn'

它引用了4参数方法定义的行

在这种情况下,我试图用 5 个参数调用重载,所以我不明白为什么编译器认为我要调用只需要 4 个参数的函数。

完整的上下文太复杂了,无法给出完整的代码示例,但可以说这一切都发生在一个类模板内,它有很多本地的typedefs,包括samp_typeconst_sampsamp_vec 等。这些都是包含 POD 类型的模板参数的 typedef,或者是其中一种 POD 类型的 std::array

typedef int_fast16_t                                fast_int;
typedef typename std::add_const< fast_int >::type   const_fast_int;

typedef samp_type (*func_type)(const_samp, const_samp);

template<func_type operation, const_fast_int strideA, const_fast_int strideB, const_fast_int strideOut>
static inline samp_vec OutOfPlaceReturn(const std::array<samp_type, strideA * vectorLen> &a,
                                        const_fast_int strideA,
                                        const std::array<samp_type, strideB * vectorLen> &b,
                                        const_fast_int strideB,
                                        const_fast_int strideOut)
{
    std::array<samp_type, vectorLen * strideOut> output;
    for(fast_int i = 0; i < vectorLen; ++i)
        output[i * strideOut] = operation(a[i * strideA], b[i * strideB]);
    return output;
}
template<func_type operation, const_fast_int strideA, const_fast_int strideOut>
static inline samp_vec OutOfPlaceReturn(const std::array<samp_type, strideA * vectorLen> &a,
                                        const_fast_int strideA,
                                        const_samp_ref b,
                                        const_fast_int strideOut)
{
    std::array<samp_type, vectorLen * strideOut> output;
    for(fast_int i = 0; i < vectorLen; ++i)
        output[i * strideOut] = operation(a[i * strideA], b);
    return output;
}

如果我理解正确的话,调用模板函数时,不需要提供编译器可以通过函数参数推导出的模板参数,所以调用看起来像这样

static samp_vec subtract(const_vec_ref a, const_fast_int strideA, const_vec_ref b, const_fast_int strideB, const_fast_int strideOut)
{   return OutOfPlaceReturn<MathClass::subtract>(a, strideA, b, strideB, strideOut);    }

那么,我调用这些模板方法的方式有问题吗?我期望编译器解决重载的方式有问题吗?

编辑

我正在使用 VS2010。到目前为止,模板和 C++11 数据类型都非常好。不确定我的编译器是否表现不佳

【问题讨论】:

  • 不要认为它解释了错误,但拥有模板参数strideA 和函数参数strideA 并不是一个好主意。您可能会放弃函数参数,而只在定义中使用模板参数。
  • 我尝试从函数参数中删除 strideA、strideB 和 strideOut。编译器仍然抱怨,但这次有点不同:too many template arguments。在我看来,这基本上是同一个问题:编译器无法弄清楚我的意思是哪个模板方法。
  • 您似乎对模板参数的工作方式感到困惑。您尝试使用非类型模板,然后在参数列表中重新声明它们,然后不要在调用中传递它们。这一切都很奇怪。
  • 我似乎从根本上理解了模板参数的工作原理。我没有使用它们的经验。我试图应用在编译时已知步幅值的约束。我看到如何将这些信息直接放入模板参数而不从函数签名中删除它们有点奇怪。这是它的奇怪之处,还是还有其他什么东西?我可以就更好的方法来做我想做的事情提出任何建议。

标签: c++ c++11 overloading function-templates


【解决方案1】:

仅对可以实例化的模板进行重载解析。这就是SFINAE 起作用的部分原因。

在您的情况下,您的 5 arg 重载具有模棱两可的 strideOut。是不是模板参数?

【讨论】:

  • 其实strideOut的函数参数声明(两者都有)是无效的,因为模板参数的名称不能在模板中重新声明。
  • @Potatoswatter:现在我看了,strideAstrideB 也是。 4-arg 版本与strideOutstrideA 有几乎相同的问题。我猜编译器只是放弃了。
  • 他似乎还希望推断出strideA * vectorLen,也许是通过隐式除法。最好的建议可能是一次迈出一步:)
  • vectorLen 是包含所有这些方法的类的模板参数。 @MSalters 为什么 strideOut 模棱两可?
  • @xaviersjs:您尝试将strideOut 作为模板参数和常规参数传递。
猜你喜欢
  • 1970-01-01
  • 2021-11-26
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
  • 2018-05-12
  • 1970-01-01
  • 1970-01-01
  • 2022-08-05
相关资源
最近更新 更多