0

一个典型的函数模板签名:

template<typename Iterator, typename T>
T fn(Iterator first, Iterator last, T init)
{
    T result;
    // ...
    return result;
}

问题是,当我这样称呼它时:

std::vector<long> data(1000,1);
fn(data.begin(), data.end(), 0);

或任何其他没有明确调用的方式

fn<std::vector<long>::iterator, long>(data.begin(), data.end(),0);

那么 T 的类型是int,并且存在溢出和错误结果的风险fn

那么我该如何专门fn化以便调用

fn(data.begin(), data.end(), 0);

是明确的并导致T设置为Iterator::value_type? 选择

template<Iterator>
typename iterator_traits<Iterator>::value_type fn(Iterator first, Iterator last, typename iterator_traits<Iterator>::value_type init)
{
    //...
}

导致来自 g++/clang++ 的模棱两可的调用错误。

编辑:

我现在看到了我的错误,上面的代码适用于下面的@Lightness Races 建议。谢谢您的帮助。

4

2 回答 2

2

为什么不简单地通过很长时间?

fn(data.begin(), data.end(), 0L);

除此之外,您可能还可以执行以下操作:

#include <type_traits>

template<typename Iterator>
typename std::iterator_traits<Iterator>::value_type fn(
   Iterator first,
   Iterator last,
   typename std::iterator_traits<Iterator>::value_type init
);

现场演示

不过,我真的不明白你是如何面临溢出风险的。

于 2014-01-09T16:26:25.480 回答
1

作为:

0 is an int
0L is a long

您只需要使用正确的参数调用该方法:

  • 直接使用正确的文字

作为:

fn(data.begin(), data.end(), 0L);
  • 或者,您可以使用中间变量

作为:

long init = 0; // result in 0L

fn(data.begin(), data.end(), init);
  • 或者您可以转换值:

作为:

fn(data.begin(), data.end(), static_cast<long>(0));

fn避免正确调用它的一种编写方法是

template<typename Iterator>
auto fn(Iterator first, Iterator last, typename std::decay<decltype(*first)>::type init)
    -> typename std::decay<decltype(*first)>::type;
于 2014-01-09T16:18:58.327 回答