在函数签名中声明和命名类型,以便可以在函数中重复使用

问题描述 投票:0回答:1

我有一个实用函数,用于根据函子转换可交互对象。

template<typename Iterable, typename Functor>
auto transform(Iterable const& input, Functor&& transformer) -> std::vector<decltype(transformer(*input.cbegin()))>
{
    std::vector<decltype(transformer(*input.cbegin()))> output;
    std::for_each(
        std::cbegin(input),
        std::cend(input),
        [&output, &transformer](auto const& m) { output.emplace_back(transformer(m)); });
    return output;
}

void test_transform()
{
    std::vector<int> ints { 10, 20, 30 };
    auto transformer = [](int i) { return std::to_string(i + 1); };
    std::vector<std::string> strs = VectorUtil::transform(ints, transformer);
    for (std::string s : strs) { std::cout << s << std::endl; }
}

必须将返回类型写两次,这是相当难看的。有没有办法给

decltype(transformer(*input.cbegin()))
std::vector<decltype(transformer(*input.cbegin()))>
命名,以便可以重复使用?

c++ decltype function-templates
1个回答
0
投票

最漂亮的选择是完全删除返回类型并声明它

auto
,这意味着该函数将推导返回类型。 对于您的情况来说,这很可能没问题,但也许您不能这样做。

如果您确实坚持要声明返回类型,仍然可以选择使用别名模板来简化它。

std::result_of
std::invoke_result
没有用,因为它们没有给你一个漂亮而简短的返回类型,这似乎就是这里的重点。

template <typename Iterable, typename Functor>
using transform_result_t =
  std::vector<decltype(std::declval<Functor&>()(*std::declval<Iterable&>().cbegin())>;

这样的别名模板可以按如下方式使用:

template<typename Iterable, typename Functor>
auto transform(Iterable const& input, Functor&& transformer)
  -> transform_result_t<Iterable, Functor>
{
    transform_result_t<Iterable, Functor> output;
    // ...
}
© www.soinside.com 2019 - 2024. All rights reserved.