Why does iterator type deduction fail? [duplicate]

浪尽此生 提交于 2020-01-09 11:56:26

问题


Why does this not work in C++?
Why can't I restrict foo's parameter to std::vector<T>::iterator like this, and what is the best workaround?

#include <vector>

template<class T>
void foo(typename std::vector<T>::iterator) { }

int main()
{
    std::vector<int> v;
    foo(v.end());
}

The error is:

In function ‘int main()’:
     error: no matching function for call to ‘foo(std::vector<int>::iterator)’
     note: candidate is:
    note: template<class T> void foo(typename std::vector<T>::iterator)
    note:   template argument deduction/substitution failed:
     note:   couldn’t deduce template parameter ‘T’

回答1:


The main reason it doesn't work is because the sandard says that the T here is in a non-deduced context. The reason why the context is not deduced is because when you pass some type to the function, the compiler would have to instantiate every single possible std::vector (including for types not present in this particular translation unit) in order to try to find one which had a corresponding type.

Of course, in case of std::vector, the compiler could contain some magic to make this work, since the semantics of the class are defined by the standard. But generally, TemplateClass<T>::NestedType can be a typedef to literally anything, and there's nothing the compiler can do about it.




回答2:


Simple.

struct X {};
template<> class std::vector<X> {
    typedef std::vector<int>::iterator iterator;
};

Oops.

Templates are Turing-Complete. You are asking the compiler to infer the arguments from the results. This is impossible in the general case, even ignoring the possibility of non-one-to-one correspondence.

Typically, you take the iterator type itself as template parameter. This permits other random-access iterators like deque, circular buffer, etc.



来源:https://stackoverflow.com/questions/15208628/why-does-iterator-type-deduction-fail

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!