解决模板参数推导中的模糊调用

时间:2014-01-09 16:00:34

标签: c++ templates argument-deduction

典型的功能模板签名:

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的类型是intfn存在溢出和不良结果的风险。

那么我如何专门化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建议。谢谢你的帮助。

2 个答案:

答案 0 :(得分: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
);

Live demo

但是,我并没有真正看到你如何面临溢出的风险。

答案 1 :(得分: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);
  • 或者你可以施放价值:

as:

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;