了解模板参数推导

时间:2015-06-26 06:49:57

标签: c++ templates

请考虑以下代码:

#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'
}

DEMO

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

2 个答案:

答案 0 :(得分:5)

typename std::vector<T>::iterator

iterator(依赖类型)代码中不可推导,因为它位于嵌套的名称说明符中,标准显示为

§14.8.2.5/ 4

  

但是,在某些上下文中,该值不参与类型推导,而是使用模板参数的值,这些参数可以在别处推导或显式指定。 如果模板参数仅在非推断的上下文中使用且未明确指定,则模板参数推断将失败。

和§14.8.2.5/ 5

  

未推断的上下文是:

     

- 使用qualified-id。

指定的类型的嵌套名称说明符

所以这是一个非演绎的背景。

可能的解决方法:

  1. 传递矢量引用而不是迭代器
  2. 使用代码分派和compile time assertions验证迭代器

答案 1 :(得分:4)

我想在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());
}