I'm trying to pass an iterator as a template parameter to a template method, but the compiler complains that:
error C2783: 'void Test::Assert(std::vector<T>::const_iterator)':
could not deduce template argument for 'T'
The code that produces the error is:
#include "stdafx.h"
#include <iostream>
#include <vector>
class Test
{
public:
template <typename T>
void Assert(typename std::vector<T>::const_iterator it)
{
std::cout << *it << std::endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Test test;
std::vector<double> myVec;
test.Assert(myVec.cbegin());
return 0;
}
I'm guessing there is a simple way to make this work, since most of the std algorithms can deduce type from iterator.
The reason is that the form you have T
in is a non-deduced context:
template <typename T>
void Assert(typename std::vector<T>::const_iterator it)
Consider a simpler case to understand why:
struct A { using type = int; };
struct B { using type = int; };
struct C { using type = int; };
template <typename T>
void Assert(typename T::type it) { ... }
Assert(5);
What should T
deduce as? It's impossible to determine. You'd have to explicitly provide the type... as something like Assert<A>(5)
.
See also What is a nondeduced context?
since most of the std algorithms can deduce type from iterator.
That's because the standard algorithms just deduce the iterator type, not the container type. For instance std::find
is just:
template <class InputIt, class T>
InputIt find( InputIt first, InputIt last, const T& value );
There is no concept of "container" here at all - it's just the iterator type that needs to be deduced. That's part of the beauty of the algorithms library.
So if what you want to do is just output the contents of the iterator, the correct function would just be:
template <typename Iterator>
void Assert(Iterator it)
{
std::cout << *it << std::endl;
}
When you call Assert(myVec.cbegin())
, Iterator
will get deduced as std::vector<double>::const_iterator
, which is exactly what you want.
The standard algorithms look like this:
template <typename Iterator>
void some_algorithm(Iterator first, Iterator last) {
// do stuff
}
If they need the type of the iterator, they can use typename std::iterator_traits<Iterator>::value_type
.
What they don't do is reference a container such as vector
in any way. Not all iterators come from containers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With