[英]Why does this code fail to compile?
I know it's a pretty general title, but I have some code and it strikes me as weird that it cant compile. 我知道这是一个相当笼统的标题,但我有一些代码,它无法编译很奇怪。
Here is a demo of the issue. 这是该问题的演示。 If you change scalar_t
from double
to float
the code compiles fine. 如果将scalar_t
从double
更改为float
则代码可以正常编译。 Why cant float be promoted to double here? 为什么不能在这里将浮动货币提高一倍? In fact, if you change the constants to double
s ( 1.0
) or int
s ( 1
) they also cant be promoted. 实际上,如果将常数更改为double
s( 1.0
)或int
s( 1
),它们也将无法提升。 Isn't this the kind of thing that should just work? 这不是应该起作用的事情吗?
Full code sample: 完整代码示例:
#include <valarray>
#include <numeric>
#include <iterator>
#include <iostream>
template<typename T>
T sigmoid(const T &in)
{
return 1.f / (1.f + std::exp(-in));
}
template<typename T>
T logit(const T &in)
{
return std::log(in / (1.f - in));
}
using scalar_t = double;
int main(int argc, char **argv)
{
std::valarray<scalar_t> f = { 0.1f, 0.3f, 0.5f, 0.9f };
scalar_t alpha = 0.5f;
scalar_t beta = -1.f;
auto lC = logit(f);
std::valarray<scalar_t> skC = alpha * lC + beta;
auto sC = sigmoid(skC);
std::copy(std::begin(sC), std::end(sC), std::ostream_iterator<scalar_t>(std::cout, " "));
std::cout << std::endl;
scalar_t num = 0.7f;
auto lS = logit(num);
auto sS = sigmoid(alpha * lS + beta);
std::cout << sS << std::endl;
return 0;
}
The operator -
you are using is defined as 您正在使用的operator -
定义为
template <class T> std::valarray<T> operator- (const T& val, const std::valarray<T>& rhs);
This meas that it expects val
to be the same type as the elements in the valarray
. 这意味着它期望val
与valarray
的元素具有相同的类型。 Since you are using a float
when template argument deduction happens it sees that val
is a float
but rhs
has a element type of double
. 由于在进行模板参数推导时使用的是float
,因此可以看到val
是float
而rhs
的元素类型为double
。 since these types do not match the deduction fails and you get a compiler error. 由于这些类型不匹配,推论失败,并且您得到编译器错误。 Remember no conversions happen during template argument deduction. 请记住,模板参数推导过程中不会发生任何转换。
This spawned a pretty interesting discussion about how to use constants in these type agnostic templates. 这引发了关于如何在这些类型不可知的模板中使用常量的有趣讨论。 Surprisingly there seems to be an answer. 令人惊讶的是似乎有一个答案。 Examining the sigmoid
function, we see that it also uses float
constants with a valarray<double>
but doesnt exhibit a compiler error. 检查sigmoid
函数,我们发现它也使用带有valarray<double>
float
常量,但没有出现编译器错误。 This is because, the std::exp(-in)
line converts the valarray<double>
to an expression template used the the standard library to optimize the computation, and for whatever reason it doesn't care about float
or double
(eg they provide the overload). 这是因为std::exp(-in)
行将valarray<double>
转换为使用标准库优化计算的表达式模板,并且无论出于何种原因,它都不关心float
或double
(例如,它们提供超载)。 So the solution I came up with was to add a unary + operator to the logit
function which does absolutely nothing except convert the valarray<double>
to an expression template which can work with the float
constant. 因此,我想出的解决方案是在logit
函数中添加一元+运算符,该函数除了将valarray<double>
转换为可以与float
常数一起使用的表达式模板外,什么也不做。
Here is the update code sample 这是更新代码示例
and the new logit
function looks like this 新的logit
函数如下所示
template<typename T>
T logit(const T &in)
{
return std::log(in / (1.f - (+in)));
}
Note the unary + operator (+in)
注意一元+运算符(+in)
Also note that NathanOliver's accepted solution answers the question as asked 另请注意,NathanOliver接受的解决方案按照要求回答了问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.