[英]Why does this code fail to compile?
我知道這是一個相當籠統的標題,但我有一些代碼,它無法編譯很奇怪。
這是該問題的演示。 如果將scalar_t
從double
更改為float
則代碼可以正常編譯。 為什么不能在這里將浮動貨幣提高一倍? 實際上,如果將常數更改為double
s( 1.0
)或int
s( 1
),它們也將無法提升。 這不是應該起作用的事情嗎?
完整代碼示例:
#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;
}
您正在使用的operator -
定義為
template <class T> std::valarray<T> operator- (const T& val, const std::valarray<T>& rhs);
這意味着它期望val
與valarray
的元素具有相同的類型。 由於在進行模板參數推導時使用的是float
,因此可以看到val
是float
而rhs
的元素類型為double
。 由於這些類型不匹配,推論失敗,並且您得到編譯器錯誤。 請記住,模板參數推導過程中不會發生任何轉換。
這引發了關於如何在這些類型不可知的模板中使用常量的有趣討論。 令人驚訝的是似乎有一個答案。 檢查sigmoid
函數,我們發現它也使用帶有valarray<double>
float
常量,但沒有出現編譯器錯誤。 這是因為std::exp(-in)
行將valarray<double>
轉換為使用標准庫優化計算的表達式模板,並且無論出於何種原因,它都不關心float
或double
(例如,它們提供超載)。 因此,我想出的解決方案是在logit
函數中添加一元+運算符,該函數除了將valarray<double>
轉換為可以與float
常數一起使用的表達式模板外,什么也不做。
這是更新代碼示例
新的logit
函數如下所示
template<typename T>
T logit(const T &in)
{
return std::log(in / (1.f - (+in)));
}
注意一元+運算符(+in)
另請注意,NathanOliver接受的解決方案按照要求回答了問題
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.