理解模板参数推导

Understanding template argument deduction

本文关键字:参数      更新时间:2023-10-16

考虑以下代码:

#include <vector>
template <typename T>
using v_itt = typename std::vector<T>::iterator;
template <typename T>
void foo(v_itt<T>){ }
int main() {
    typename std::vector<long>::iterator i = std::vector<long>().begin();
    foo(i); //candidate template ignored: couldn't infer template argument 'T'
}

演示

代码出了什么问题?我认为T应该被推导出long。有没有办法以某种方式解决这个问题?

typename std::vector<T>::iterator

iterator(依赖类型)它在代码中是不可推导的,因为它在嵌套的名称说明符中,并且标准规定

§14.8.2.5/4

然而,在某些上下文中,该值不参与类型推导,而是使用在其他地方推导或明确指定的模板参数的值如果模板参数仅在非推导上下文中使用,并且未明确指定,则模板参数推导失败

和§14.8.2.5/5

未推导的上下文为:

--使用限定id指定的类型的嵌套名称说明符。

所以这是一个非推导的上下文。

可能的解决方案:

  1. 传递向量引用而不是迭代器
  2. 使用标记调度和编译时断言来验证迭代器

我只想为Marco的答案添加一个可能的解决方法3:

#include <vector>
template<typename T>
void real_foo( typename std::vector<T>::iterator){}
template <typename T>
void foo(T i){ real_foo<typename decltype(i)::value_type>(i); }
int main() {
    std::vector<long> v;
    foo(v.begin());
}