我们如何组成在C ++中返回多个值的函数

时间:2015-01-06 11:52:13

标签: c++ c++11 c++14

我们如何编写在C ++中返回多个返回值的函数?更具体地说,如果一个函数返回一个元组,我们可以将这个函数与另一个没有明确接受元组的函数组合在一起吗?例如,在代码中:

#include <tuple>
#include <iostream>

std::tuple <int,int> tuple_ints(int x,int y) {
    return std::tuple <int,int> (x,y);
}

int add(int x,int y) {
    return x+y;
}

int main() {
    std::cout << add(tuple_ints(1,2)) << std::endl;
}

我正在尝试撰写函数addtuple_ints。这正确地产生了错误:

g++ -std=c++11 test01.cpp -o test01
test01.cpp: In function 'int main()':
test01.cpp:17:37: error: cannot convert 'std::tuple<int, int>' to 'int' for argument '1' to 'int add(int, int)'
     std::cout << add(tuple_ints(1,2)) << std::endl;
                                     ^
Makefile:2: recipe for target 'all' failed
make: *** [all] Error 1

我不想修改add来接受元组;我希望这个定义能够保持原样。我们还能做些什么来组成这两个函数吗?

编辑1

事实证明,有人建议将此功能添加到N3802下的标准库中。这类似于@ Jarod42提供的代码。我正在附加固定代码,它使用N3802中的代码作为参考。大多数情况下,不同之处在于提案中的代码似乎正确处理完美转发

#include <tuple>
#include <iostream>
#include <utility>

// This comes from N3802
template <typename F, typename Tuple, size_t... I>
decltype(auto) apply_impl(F&& f, Tuple&& t, std::index_sequence<I...>) {
    return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...);
}
template <typename F, typename Tuple>
decltype(auto) apply(F&& f, Tuple&& t) {
    using Indices = 
        std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>;
    return apply_impl(std::forward<F>(f), std::forward<Tuple>(t), Indices{});
}

// Now, for our example
std::tuple <int,int> tuple_ints(int x,int y) {
    return std::tuple <int,int> (x,y);
}

int add(int x,int y) {
    return x+y;
}

int main() {
    std::cout << apply(add,tuple_ints(1,2)) << std::endl;
}

此外,如果有任何混淆,此解决方案需要C ++ 14用于std::index_sequence之类的内容。

3 个答案:

答案 0 :(得分:9)

您可以添加一个函数来将元组调度到参数:

namespace detail
{
    template <typename F, typename TUPLE, std::size_t...Is>
    auto call(F f, const TUPLE& t, std::index_sequence<Is...>)
    -> decltype(f(std::get<Is>(t)...))
    {
        return f(std::get<Is>(t)...);
    }
}

template <typename F, typename TUPLE>
auto call(F f, const TUPLE& t)
-> decltype (detail::call(f, t,
        std::make_index_sequence<std::tuple_size<TUPLE>::value>()))
{
    return detail::call(f, t,
        std::make_index_sequence<std::tuple_size<TUPLE>::value>());
}

然后就这样称呼

std::cout << call(add, tuple_ints(1,2)) << std::endl;

Live example

答案 1 :(得分:5)

你可能想要使用一些像

这样的匿名lambda
  [](std::tuple <int,int> t){return add(get<0>(t),get<1>(t));}(tuple_int(1,2))

希望编译器能够优化该代码。

另请阅读currying

答案 2 :(得分:0)

你可以创建一个函数(比如X),它将std::tuple <int , int >作为参数,在内部它会调用int add (int x, int y)。类似的东西:

int X(std::tuple <int, int> t) {
    return add ( std::get<0>(t), std::get<1>(t) );
}

现在致电X(tuple_ints(1,2))