【问题标题】:funtion with const pointer template type parameter not called for arguments of non-const pointer type对于非 const 指针类型的参数,不调用具有 const 指针模板类型参数的函数
【发布时间】:2020-04-12 14:39:49
【问题描述】:

据我了解,const 指针函数参数应该能够接受 const 和非 const 指针。在后一种情况下,通过指针修改值是非法的。

假设我有以下模板函数

template <typename T1, typename T2>
decltype(auto) plus(T1 a, T2 b) {
    return a + b;
}

template <typename T1, typename T2>
decltype(auto) plus(const T1* a, const T2* b) {
    return *a + *b;
}

int main() {

    int a {2}, b {3};
    std::cout << plus(a, b) << std::endl;

    int *first { new int {2} }, *second { new int {3} };

    // it seems here that the return type is deduced to be void*?

    std::cout << plus(first, second) << std::endl;
}

第二个函数调用正确调用了plus模板函数,该函数接受指针参数但推断返回类型为void*

但是,如果我将模板签名更改为

template <typename T1, typename T2>
decltype(auto) plus(T1* a, T2* b) {
    return *a + *b;
}

这会产生正确的结果。

这是怎么回事?

【问题讨论】:

  • 它不会像您声称的那样调用第二个重载。它调用第一个更好的匹配(因此模板部分排序无关紧要)然后应该失败,因为添加指针没有明确定义,请参阅godbolt.org/z/djBS_k
  • 它调用第一个重载。错误消息 将表达式推导出为 void 但这是由于表达式格式错误且没有意义。
  • @walnut 正在添加通常没有为模板定义好的指针,或者没有为自动类型推导定义好的指针?
  • @MutatingAlgorithm 在 C++ 中永远不能添加两个指针。它应该始终生成错误消息。
  • 正如已经指出的那样,添加两个指针不是格式良好的 C++。如果你的编译器真的接受这个代码(它不应该),你应该向你的编译器供应商报告这个错误......

标签: c++ pointers templates decltype


【解决方案1】:

plus(first, second) 调用第一个模板重载,因为它是更好的匹配。

在模板参数推导之后(第一个产生T1 == T2 == int*,第二个产生T1 == T2 == int)两个重载都是可行的。但是,对于这两个参数中的每一个,第一个重载只需要左值到右值的转换,而第二个重载需要左值到右值的转换,然后是限定转换(添加const)。

因此,对于第一次重载,两个参数的隐式转换序列更好,因此由重载决议选择。甚至不考虑函数模板的偏序。

然而,用T1 == T2 == int* 调用第一个函数模板是不正确的,因为如果ab 都是指针类型,则不允许a + b。你的编译器应该已经在这里给你一个错误。


使用第二个模板重载的替代签名,它不需要上面提到的额外限定转换,并且两个重载的参数的隐式转换序列将相同。

因此将考虑函数模板部分排序来决定选择哪个重载,并且由于第二个模板比第一个模板更专业,因此将选择第二个模板。

使用T1 == T2 == int,它将按预期工作,因为*a + *b 添加两个int,而不是两个指针,产生int 的返回类型,因为*a + *b 是prvalue。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 1970-01-01
    • 2013-03-30
    相关资源
    最近更新 更多