[英]Implicit conversion in template type deduction
In this question the OP asks why his std::accumulate
function is returning the wrong value. 在这个问题中 ,OP询问为什么他的std::accumulate
函数返回错误的值。 The answer is because he passes in an int
for his initial value, therefore making the calculations all int
s rather than double
s. 答案是因为他将int
用作初始值,因此计算全部为int
而不是double
。 I have two versions: 我有两个版本:
template <class InputIterator, class T>
auto accumulate (InputIterator first, InputIterator last, T init)
{
typedef typename std::iterator_traits<InputIterator>::value_type vt;
vt init2 = vt(init);
// ...
return init2;
}
template <class InputIterator, class T = typename std::iterator_traits<InputIterator>::value_type>
T not_working (InputIterator first, InputIterator last, T init)
{
// ...
return init;
}
Why in version 2 is T
still an int
? 为什么在版本2中T
仍然是int
? Because of implicit conversion? 因为隐式转换?
T
is still being deduced, overwriting the default argument. 仍在推导T
,覆盖默认参数。 :) :)
You want this: 你要这个:
template <class InputIterator>
typename std::iterator_traits<InputIterator>::value_type
working(InputIterator first, InputIterator last,
typename std::iterator_traits<InputIterator>::value_type init) {
return init;
}
The answer to the immediate question was already stated: if the type can be deduced from the argument list, it will be deduced. 前面的问题已经回答了:如果可以从参数列表中推导类型,则可以推导它。 Making the used type a nested type prevents it from being deduced: 将使用的类型设置为嵌套类型可以防止推导它:
template <typename T>
struct identity {
typedef T type;
};
template <typename It, typename T = typename std::iterator_traits<It>::value_type>
T safe_accumulate(It begin, It end, typename identity<T>::type sum) {
return std::accumulate(begin, end, sum);
}
In some situations it is, however, desirable to specify the result type of the algorithm. 但是,在某些情况下,希望指定算法的结果类型。 For example, if you want to sum the char
values in a lengthy strings. 例如,如果要对较长的字符串中的char
值求和。 Using safe_accumulate()
as it is defined above makes specifying the result type a bit painful: 使用上面定义的safe_accumulate()
会使指定结果类型有些safe_accumulate()
:
std::string s("hello, world");
std::cout << safe_accumulate<std::string::iterator, long>(s.begin(), s.end(), 0) << '\n';
The implementation can be done in a way which puts the result type first: 可以通过将结果类型放在第一位的方式来实现:
template <typename T = void, typename It>
typename std::conditional<std::is_same<T, void>::value,
typename std::iterator_traits<It>::value_type,
T>::type
safe_accumulate(It begin, It end,
typename std::conditional<std::is_same<T, void>::value,
typename std::iterator_traits<It>::value_type,
T>::type sum) {
return std::accumulate(begin, end, sum);
}
Now the algorithm can be used in a more convenient way, ie, the implementer of the algorithm provided a somewhat more complicated implementation for the benefit of its users: 现在可以以更方便的方式使用该算法,即该算法的实现者为用户带来了一些更复杂的实现:
std::cout << safe_accumulate<long>(s.begin(), s.end(), 0) << '\n';
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.