簡體   English   中英

為什么此代碼無法編譯?

[英]Why does this code fail to compile?

我知道這是一個相當籠統的標題,但我有一些代碼,它無法編譯很奇怪。

是該問題的演示。 如果將scalar_tdouble更改為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);

這意味着它期望valvalarray的元素具有相同的類型。 由於在進行模板參數推導時使用的是float ,因此可以看到valfloatrhs的元素類型為double 由於這些類型不匹配,推論失敗,並且您得到編譯器錯誤。 請記住,模板參數推導過程中不會發生任何轉換。

這引發了關於如何在這些類型不可知的模板中使用常量的有趣討論。 令人驚訝的是似乎有一個答案。 檢查sigmoid函數,我們發現它也使用帶有valarray<double> float常量,但沒有出現編譯器錯誤。 這是因為std::exp(-in)行將valarray<double>轉換為使用標准庫優化計算的表達式模板,並且無論出於何種原因,它都不關心floatdouble (例如,它們提供超載)。 因此,我想出的解決方案是在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM