繁体   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