【问题标题】:Combining auto template parameters with std::optional, possible?将自动模板参数与 std::optional 结合,可能吗?
【发布时间】:2021-09-19 03:06:25
【问题描述】:

我真的很喜欢 C++17 的 auto template parameters,因为我不必为了使用非类型模板参数(例如带有转发参数的函数)而跳槽。

但这让我开始思考,如果转发函数没有有效结果,是否可以将它与其他类型(例如std::optional)结合使用。例如。类似:

#include <iostream>
#include <optional>

template <auto Func, typename E, typename ...Args>
auto safeCaller(Args&& ...args)
{
    // this could even be wrapped in a loop for retrying
    try
    {
        return Func(std::forward<Args>(args)...);
    }
    catch (E &e)
    {
        // ... perform some logging perhaps? or whatever else is relevant
        return std::nullopt;
    }
}

int foo(std::string bar)
{
    return bar.size();
}

int main()
{
    // specialise safeCaller to work on foo and to expect std::runtime_error
    auto result = safeCaller<foo, std::runtime_error>("baz");
    if (result)
    {
        std::cout << *result << std::endl;
    }
    return 0;
}

现在这有几个问题:

main.cpp: In instantiation of ‘auto safeCaller(Args&& ...) [with auto Func = foo; E = std::runtime_error; Args = {const char (&)[4]}]’:
main.cpp:25:60:   required from here
main.cpp:14:21: error: inconsistent deduction for auto return type: ‘int’ and then ‘std::nullopt_t’
   14 |         return std::nullopt;
      |                     ^~~~~~~
main.cpp:14:21: error: ‘struct std::nullopt_t’ used where a ‘int’ was expected
main.cpp: In function ‘int main()’:
main.cpp:28:23: error: invalid type argument of unary ‘*’ (have ‘int’)
   28 |         std::cout << *result << std::endl;

这是一个玩具示例,但我希望有一些东西可以充当函数/调用的装饰器,这些函数/调用可能有助于进行一些通用的异常处理、清理和/或日志记录。

我对@9​​87654325@ 的替代方案持开放态度,只要有一种方法可以表明调用无法完成,因此不会返回任何结果。

【问题讨论】:

  • 这个问题与auto模板参数没有任何关系(虽然它确实使用了它们);而是完全与auto返回类型推导和optional有关。

标签: c++ templates c++17 stdoptional


【解决方案1】:

你可以从传入的函数中推断出你想要什么类型的std::optional

如果抛出,你可以返回一个空的可选项。

#include <iostream>
#include <optional>

template <auto Func, typename E, typename ...Args>
auto safeCaller(Args&& ...args)
{
    using ret = std::optional<decltype(Func(std::forward<Args>(args)...))>;
    // this could even be wrapped in a loop for retrying
    try
    {
        return ret{Func(std::forward<Args>(args)...)};
    }
    catch (E &e)
    {
        // ... perform some logging perhaps? or whatever else is relevant
        return ret{};
    }
}

int foo(std::string bar)
{
    return bar.size();
}

int main()
{
    // specialise safeCaller to work on foo and to expect std::runtime_error
    auto result = safeCaller<foo, std::runtime_error>("baz");
    if (result)
    {
        std::cout << *result << std::endl;
    }
    return 0;
}

【讨论】:

  • 这很好,我不会想到像那样操作optional 类型。我认为这是我需要的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-18
  • 1970-01-01
  • 1970-01-01
  • 2017-05-14
  • 2012-06-18
  • 1970-01-01
相关资源
最近更新 更多