【问题标题】:Function Overloading, Could Not Deduce Template Argument函数重载,无法推断模板参数
【发布时间】:2012-10-01 06:59:05
【问题描述】:

我正在尝试重载 Sum 函数,该函数接受 [list or vector] 开始和结束迭代器作为参数。这个编译器错误真的让我很困惑。相关代码如下:

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

}

我收到以下编译器错误:

iterators.cpp(72): 错误 C2783: 'const double Sum(const T1::const_iterator &,const T2::const_iterator &)' : 无法推断 'T1' 的模板参数

iterators.cpp(72): 错误 C2783: 'const double Sum(const T1::const_iterator &,const T2::const_iterator &)' : 无法推断 'T2' 的模板参数

iterators.cpp(72): 错误 C2780: 'const double Sum(const std::map &)' : 需要 1 个参数 - 提供 2 个

iterators.cpp(72): 错误 C2780: 'const double Sum(const T &)' : 需要 1 个参数 - 提供 2 个

编译器如何无法识别我正在尝试使用两个输入调用 Sum 函数?函数调用不正确?

谢谢!

【问题讨论】:

    标签: c++ templates stl iterator overloading


    【解决方案1】:

    您不需要告诉它迭代器必须是某些类型的成员T1 和T2,只需在迭代器类型本身上对其进行模板化:

    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;
    }
    

    还有一个标准的std::accumulate 可以做到这一点:

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

    【讨论】:

    • 我怎样才能让它们保持不变呢?
    • @Clark 你不能。您可能不想这样做; iterator 和 const_iterator 之间的区别在很多情况下是不相关的(例如输入迭代器)。如果您将模板记录为接受输入迭代器(template &lt;typename InputIterator&gt;,而不仅仅是Iter),那么很明显该函数不会改变序列。否则,你证明它没有。
    【解决方案2】:

    首先,我认为您不想这样做。并非所有序列都有 底层容器。 (例如,想想istream_iterators。)并且 更重要的是,你明显允许(甚至鼓励) 来自不同容器的开始和结束迭代器;没有没有的情况 在T1 和T2 有的地方你可以合法地使用这个功能 不同种类。模板应该有一个参数,它 应该是一个迭代器;按照惯例,对 迭代器应以参数名称表示,例如 InputIterator(此处为案例)、ForwardIterator等

    为什么你的代码不能编译:

    在大多数情况下,使用的类型、模板和非类型值 组成 P 参与模板参数推导。也就是说,他们 可用于确定模板参数的值,并且 如此确定的值必须与确定的值一致 别处。然而,在某些情况下,该值不 参与类型推导,而是使用模板的值 在别处推导出来或明确指定的论点。 如果模板参数仅在非推导上下文中使用并且是 未明确指定,模板参数推导失败。

    未推断的上下文是:

    - 使用指定的类型的嵌套名称说明符 合格的ID。

    [...]

    (来自 §14.8.2.5/4,5。)

    【讨论】:

      【解决方案3】:

      这样调用方法..

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

      【讨论】:

        猜你喜欢
        • 2013-02-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-22
        • 2020-07-01
        • 1970-01-01
        相关资源
        最近更新 更多