简体   繁体   中英

Function Overloading, Could Not Deduce Template Argument

I'm trying to overload a Sum function which accepts a [list or vector] start and end iterator as arguments. This compiler error is really confusing me. Relevant code is as follows:

template <typename T1, typename T2>
const double Sum(const typename T1::const_iterator& start_iter, const typename T2::const_iterator& end_iter)
{// overloaded function that calculates sum between two iterators
    typename T1::const_iterator iterator_begin = start_iter;
    typename T2::const_iterator iterator_end = end_iter;

    double my_sum = 0;

    for (iterator_begin; iterator_begin != iterator_end; iterator_begin++)
        my_sum += *iterator_begin;

    return my_sum;      
}

int main()
{

list<double> test_list(10,5.1);
cout << Sum(test_list.begin(), test_list.end()); // compiler errors here

}

I get the following compiler errors:

iterators.cpp(72): error C2783: 'const double Sum(const T1::const_iterator &,const T2::const_iterator &)' : could not deduce template argument for 'T1'

iterators.cpp(72): error C2783: 'const double Sum(const T1::const_iterator &,const T2::const_iterator &)' : could not deduce template argument for 'T2'

iterators.cpp(72): error C2780: 'const double Sum(const std::map &)' : expects 1 arguments - 2 provided

iterators.cpp(72): error C2780: 'const double Sum(const T &)' : expects 1 arguments - 2 provided

How is the compiler not recognizing I'm trying to call the Sum function with two inputs? I'm calling the function incorrectly?

Thanks!

You dont need to tell it that iterators have to be members of some types T1 and T2 , just template it on iterator type itself:

template <typename Iter>
const double Sum(Iter iterator_begin, Iter iterator_end)
{
    double my_sum = 0;
    for (; iterator_begin != iterator_end; ++iterator_end)
        my_sum += *iterator_begin;
    return my_sum;      
}

int main()
{
    std::list<double> test_list;
    std::cout << Sum(test_list.begin(), test_list.end());
    return 0;
}

also there is a standard std::accumulate that does this:

int main()
{
    std::list<double> test_list;
    std::cout << std::accumulate(test_list.begin(), test_list.end(), 0.0);
    return 0;
}

First, I don't think you want to do this. Not all sequences have an underlying container. (Think of istream_iterator s, for example.) And more importantly, you're distinctly allowing (and even encouraging) begin and end iterators from different containers; there is no case where you could legally use this function where T1 and T2 have different types. The template should have a single parameter, which should be an iterator; and by convention, the constraints on the iterator should be expressed in the name of the parameter, eg InputIterator (the case here), ForwardIterator , etc.

As to why your code doesn't compile:

In most cases, the types, templates, and non-type values that are used to compose P participate in template argument deduction. That is, they may be used to determine the value of a template argument, and the value so determined must be consistent with the values determined elsewhere. In certain contexts, however, the value does not participate in type deduction, but instead uses the values of template arguments that were either deduced elsewhere or explicitly specified. If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.

The non-deduced contexts are:

— The nested-name-specifier of a type that was specified using a qualified-id.

[...]

(From §14.8.2.5/4,5.)

这样的调用方法

Sum<list<double>,list<double> >(test_list.begin(), test_list.begin());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM