我有一个实用函数,用于根据函子转换可交互对象。
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()))>
命名,以便可以重复使用?
最漂亮的选择是完全删除返回类型并声明它
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;
// ...
}