Can't deduce template type

爷,独闯天下 提交于 2019-11-30 03:03:35

问题


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.


回答1:


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.




回答2:


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.




回答3:


template <typename Ite>
void Assert(Ite &&it)
{
    std::cout << *std::forward<It>(it) << std::endl;
}

That's it - the standard library just parameterizes on the whole type of the iterator. In fact, anything that behaves like an iterator can be used (that's the main reason why iterators behave like pointers). This is called "duck typing".

What you are trying to do (restricting the function to only those types which are explicit iterators) is what C++17 concepts are about.




回答4:


#include "stdafx.h"
#include <iostream>
#include <vector>

class Test
{
 public:
    template <typename T>
    void Assert(typename T::const_iterator it)
    {
        std::cout << *it << std::endl;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
   Test test;

   std::vector<double> myVec;

   test.Assert<std::vector<double> >(myVec.cbegin());

   return 0;
}

Try out this once.




回答5:


The following code is compiled ok using clang.

#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 main(int argc, char* argv[])
{
    Test test;

    std::vector<double> myVec;

    myVec.push_back(2.0f);

    test.Assert<double>(myVec.cbegin());  // call Assert in this way.

    return 0;
}

The outputs:

$ ./a.out
2

The compiler's version:

$ clang++ -v
Apple LLVM version 6.1.0 (clang-602.0.49) (based on LLVM
3.6.0svn) Target: x86_64-apple-darwin14.1.0 Thread model: posix


来源:https://stackoverflow.com/questions/29677522/cant-deduce-template-type

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