簡體   English   中英

std::transfrom 中未解決的重載 function 類型

[英]Unresolved overloaded function type in std::transfrom

我正在嘗試為doublevector<double>編寫重載 function 。

我剛剛做了以下事情:


constexpr double degrees(double val) { return v * M_1_PI * 180.0; }

std::vector<double> degrees(const std::vector<double>& val)
{
    std::vector<double> out;
    out.reserve(val.size());
    std::transform(val.begin(), val.end(), std::back_inserter(out), degrees);
    return out;
}

我希望這是相當簡單的,但它不能編譯,我無法弄清楚。 編譯器無法解析重載degrees function,一直報錯

couldn't deduce template parameter '_UnaryOperation'

編輯:用reserve修復部分,這是一個明顯的錯誤。

您需要指定應將哪個重載傳遞給std::transform 例如

std::vector<double> degrees(const std::vector<double>& val) {
    std::vector<double> out;
    out.reserve(val.size());
    std::transform(val.begin(), val.end(), std::back_inserter(out), static_cast<double(*)(double)>(degrees));
    //                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    return out;
}

順便說一句: std::vector<double> out(val.size()); out構造為包含值為0.0val.size()元素。 我想這不是你想要的。 默認初始化和reserve就可以了。

主要有兩個問題

  1. 有兩個函數重載編譯器無法自動選擇它,使用哪一個。 因此,您需要明確指定將哪一個傳遞給std::transform

  2. std::vector<double> out(val.size()); 將創建一個大小val.size()的 double 向量,所有元素都將以0.0啟動。 std::back_inserter(out)然后在這些之后添加元素。 據推測,您不希望在實際元素之前在out向量中有val.size()數量為0.0 s。 對於不需要的真實位置,您需要一個std::vector::reserve

That being said, I would suggest having a lambda function instead of a free function, which has the advantage of having the implementation of the function right into the place where it is called:

std::vector<double> degrees(const std::vector<double>& val)
{
    std::vector<double> out;
    out.reserve(val.size()); // reserve some memory
    std::transform(val.begin(), val.end(), std::back_inserter(out),
        [](double ele) {return ele * M_1_PI * 180.0; }
    );
    return out;
}

查看演示

你不能傳遞一個重載集,但你可以傳遞一個帶有重載調用運算符的函子:

struct degrees {
    constexpr double operator()(double val) {return val * 0.3 * 180.0;}

    std::vector<double> operator()(const std::vector<double>& val) {
        std::vector<double> out(val.size());
        std::transform(val.begin(), val.end(), std::back_inserter(out), degrees{});
        return out;
    }
};

我不想相信提問者不知道他們定義了兩個同名的函數degrees ,所以我會給我的答案另一種陰影。

怎么可能,在這個電話里

std::transform(val.begin(), val.end(), std::back_inserter(out), degrees);

那個degrees不知道? 我的意思是, std::transform應該嘗試對val中的每個元素應用degrees ,並且由於這些元素中的每一個都是double ,因此 transform 應該利用第一個重載,即采用double的重載不是很明顯嗎?

然而,盡管這種動機可能令人信服,但它需要編譯器將決定應該調用什么degrees的決定延遲到實際調用的那一刻,即不是在std::transform的調用站點,而是std::transform (特別是在 cppreference 文檔頁面上的這個可能的實現中評估表達式unary_op(*first1++)時)。

這根本不可能,因為規則是編譯器必須在 function 的調用站點知道它的 arguments 是什么。 參考這個例子,在std::transform的調用點,編譯器不知道需要哪個degree的重載。

一種解決方法是在 function object 中使用重載的operator()包裝degrees ,如463035818_is_not_a_number所建議的那樣; 這樣做, object degrees將在std::transform調用站點知道,並且僅std::transform內部,在對象的operator()的調用站點,編譯器必須在operator()的重載之間進行選擇。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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