【问题标题】:Convert exception to optional: cant resolve overloaded function type将异常转换为可选:无法解析重载的函数类型
【发布时间】:2014-12-29 18:11:34
【问题描述】:

我正在尝试构建一个将异常转换为可选的通用函数:

template<typename Func, typename... Args>
auto get_opt(Func f, Args&&... args)
{
    auto ret = std::experimental::optional<decltype(f(std::forward<Args>(args)...))>();
    try
    {
        ret = f(std::forward<Args>(args)...);
    }
    catch(const std::exception&)
    {}

    return ret;
}

然后我可以将它与任何可能引发异常的函数一起使用,并且它适用于没有重载的函数:

int test(const std::string& s)
{
    return std::stoi(s);
}

int main(int argc, char** argv)
{
    auto n = get_opt(test, "1234");

    if(n)
    {
        std::cout << "value: " << *n << std::endl;
    }
}

问题是如果我使用具有重载的函数,编译器会抱怨他不知道要调用什么重载:

auto n = get_opt(std::to_string, 1234);

main.cpp:25: error: no matching function for call to 'get_opt(<unresolved overloaded function type>, int)'

这个应该调用std::to_string(int)重载。

  1. 我的get_opt 函数格式正确吗?是args 的通用参考并使用std::forward 来处理这种情况吗?

  2. 既然传递了参数int,为什么编译器看不到要调用的重载,他应该正确计算出正确的重载?

  3. 如何使其适用于重载?

提前致谢。

【问题讨论】:

    标签: c++ templates boost


    【解决方案1】:

    这里的问题在于模板类型推导,是完美的转发失败之一。当你有一个重载的函数时,应该为Func推导出哪一个?

    有两种方法可以解决这个问题。要么创建一个正确类型的函数指针并将其传入,要么将to_string 转换为该类型:

    using FuncType = std::string(*)(int );
    FuncType f = std::to_string;
    
    auto n = get_opt(f, 1234); 
    auto n2 = get_opt(static_cast<FuncType>(std::to_string), 1234);
    

    【讨论】:

    • 非常感谢您的回答。它不能推断出 Func 是完全有道理的,出于某种原因,我认为编译器可以为此使用 Args,但显然他不能。演员表有效,但我想让它更干净,我试过: template auto get_opt(Ret(*f)(Args...), Args&&... args) 然后我会这样调用函数: auto n = get_opt<:string>(std::to_string, 1234);但我得到完全相同的错误。但是现在他应该能够推断出这个函数吧?我给他返回类型和参数类型。
    • @sap 同样的原因。 std::to_string 没有类型。没有类型 == 没有类型推导,所以没有办法让它工作。
    【解决方案2】:

    我的get_opt 函数格式正确吗? args 的通用参考和使用std::forward 是解决这种情况的方法吗?

    是的。

    既然传递了参数 int,为什么编译器看不到要调用的重载,他应该找出正确的重载吗?

    编译器不会检查函数调用以查看应该选择哪个重载。事实是,当您有一个重载函数时,仅通过其名称引用该函数会导致歧义,因为它可能是多个函数。它实际上是一种“未解析的重载函数类型”。

    您通常可以通过转换为正确的类型来解决此问题,但如果您的函数使用模板参数推导,您将无法在 get_opt 内的调用站点实现这一点。你可以用 lambda 表达式解决这个问题:

    auto glambda = [&] (auto&& x) { return std::to_string(x); });
    auto n = get_opt(glambda, 1234);
    

    【讨论】:

    • 非常感谢,我想没有别的办法了。现在我需要的是一个通用函数,它为任何给定函数返回一个 lambda!哦等等……
    • @sap 可以用宏来完成。
    猜你喜欢
    • 1970-01-01
    • 2012-09-29
    • 1970-01-01
    • 2012-03-07
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 2020-05-08
    • 1970-01-01
    相关资源
    最近更新 更多