簡體   English   中英

返回具有自動返回類型的 std::function

[英]Return a std::function with auto return type

我想創建一個仿函數來將 std::string 轉換為不同的類型。

std::function<auto(const std::string)> create(const std::string &type)
{
  if(type=="int") {
    return [&](const std::string &value){return std::stoi(value);}
  } else if(type=="float") {
    return [&](const std::string &value){return std::stof(value);}
  }  else {
    throw std::runtime_error("");
  }
}

但似乎我們不能在這里使用auto作為std::function的返回類型。

有人可以建議一種方法嗎?

對於一個 function 或一個 function 模板的實例化,返回類型必須相同且固定。 您可以將 function 模板制作為

template <typename R>
std::function<R(const std::string&)> create()
{
  if(std::is_same<R, int>::value) {
    return [](const std::string &value){return std::stoi(value);};
  } else if(std::is_same<R, float>::value) {
    return [](const std::string &value){return std::stof(value);};
  }  else {
    throw std::runtime_error("");
  }
}

然后像使用它

auto f_int = create<int>();
auto f_float = create<float>();

由於 C++17 您可以使用constexpr if ,因此在編譯時將丟棄不必要的語句。

template <typename R>
std::function<R(const std::string&)> create()
{
  if constexpr (std::is_same_v<R, int>) {
    return [](const std::string &value){return std::stoi(value);};
  } else if constexpr (std::is_same_v<R, float>) {
    return [](const std::string &value){return std::stof(value);};
  }  else {
    throw std::runtime_error("");
  }
}

順便說一句:作為返回類型, std::function的參數應該是const std::string& 而 lambda 似乎不需要捕獲任何東西。

BTW2:根據您使用返回值的方式,直接返回 lambda 而不是將其包裝到std::function中也可能就足夠了。

template <typename R>
auto create()
{
  if constexpr (std::is_same_v<R, int>) {
    return [](const std::string &value){return std::stoi(value);};
  } else if constexpr (std::is_same_v<R, float>) {
    return [](const std::string &value){return std::stof(value);};
  }  else {
    throw std::runtime_error("");
  }
}

我認為不可能在std::function中進行自動返回類型扣除。

如果您需要存儲調用std::sto* function 的 lambda/仿函數,我想出了一些替代方案。 只需自己創建一個模板並用它替換auto 這允許您刪除const std::string&類型參數。

#include <type_traits> // for std::is_same

template <typename T = int>
constexpr std::function<T(const std::string)> create()
{
    if (std::is_same<T, int>::value)   
    { return [&](const std::string &value) { return std::stoi(value); }; }

    if (std::is_same<T, float>::value) 
    { return [&](const std::string &value) { return std::stof(value); }; }

    throw std::runtime_error("");
}

或者您可以自己創建一個函子 class。

#include <type_traits> // for std::is_same

template <typename T = int>
struct Functor {

    T operator()(const std::string& input) {
        if (std::is_same<T, int>::value)   { return std::stoi(input); };
        if (std::is_same<T, float>::value) { return std::stof(input); };
        throw std::runtime_error("");
    }

};

以上用途。

int main() {
    
    auto f_i = create();
    auto f_f = create<float>();
    f_i("42");   // returns an int
    f_f("3.14"); // returns a float
    
    Functor fo_i;
    Functor<float> fo_f;
    fo_i("42");   // returns an int
    fo_f("3.14"); // returns a float
    
}

我建議簡單地調用正確的數字轉換 function 而不是存儲調用std::sto*的 lambda/functor 會是更好的方法。

暫無
暫無

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

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