【问题标题】:Make variadic function which takes arbitary functors and returns a tuple of each return value of input functors制作可变参数函数,它接受任意函子并返回输入函子的每个返回值的元组
【发布时间】:2013-02-25 02:35:47
【问题描述】:

我想创建一个函数对象,它接受任意函数对象并返回一个元组,该元组存储每个函数对象的返回值。

为了实现这个目标,我发了class A

class A
{
private:
    template <class Ret, class Func>
    auto impl(Ret ret, Func func) -> decltype(tuple_cat(ret, make_tuple(func())))
    {
        return tuple_cat(ret, make_tuple(func()));
    }

    template <class Ret, class First, class... Funcs>
    auto impl(Ret ret, First first, Funcs... funcs) 
    -> decltype(impl(tuple_cat(ret, make_tuple(first())), funcs...))
    {
    return impl(tuple_cat(ret, make_tuple(first())), funcs...);
    }

public:
    template <class Func>
    auto operator()(Func func) -> decltype(make_tuple(func()))
        {
        return make_tuple(func());
    }

    template <class First, class... Funcs>
    auto operator()(First first, Funcs... funcs)
     -> decltype(impl(make_tuple(first()),funcs...))
    {
        impl(make_tuple(first()),funcs...);
    }
};

在主函数中,我做了三个 lambdas。

int main(){
    auto func1 = [](){ cout << 1 << endl; return 1;};
    auto func2 = [](){ cout << 2 << endl; return 2;};
    auto func3 = [](){ cout << 3 << endl; return 3;};

    A a;
    auto x = a(func1, func2);
    cout << "ans : " << get<0>(x) << get<1>(x) << endl; // I expect ans : 12
}

这段代码可以被gcc 4.7.2编译。但是,它并没有像我预期的那样工作。 我应该如何修改这段代码?

【问题讨论】:

  • “但是,它并没有像我预期的那样工作。” 那么它是如何工作的呢?
  • 我得到了一些垃圾值。在我的电脑里,我得到了-2 1962460021

标签: c++ c++11 tuples variadic-templates


【解决方案1】:

我认为问题在于您缺少return 声明:

template <class First, class... Funcs>
auto operator()(First first, Funcs... funcs)
 -> decltype(impl(make_tuple(first()),funcs...))
{
    return impl(make_tuple(first()),funcs...);
//  ^^^^^^
}

没有它,您的代码就会出现未定义的行为。根据 C++11 标准的第 6.6.3/2 段:

[...] 从函数末尾流出相当于没有值的返回;这会在返回值的函数中导致未定义的行为。

【讨论】:

  • @Sungmin:很高兴它有帮助:-)
【解决方案2】:

明显的问题是您缺少其他答案所指出的 return 语句。

不管怎样,我觉得你做的太多了。这应该有效:

class A
{
public:
    template <class First, class... Funcs>
    auto operator()(First first, Funcs... funcs) -> decltype((make_tuple(first(),funcs()...)))
    {
        return (make_tuple(first(),funcs()...));
    }
};

int main(){
    auto func1 = [](){ cout << 1 << endl; return 1;};
    auto func2 = [](){ cout << 2 << endl; return 2;};

    A a;
    auto x = a(func1, func2);
    cout << "ans : " << get<0>(x) << get<1>(x) << endl; // I expect ans : 12
}

Online Demo

【讨论】:

  • 非常感谢。我刚刚看到你的代码。它与 mfontanini 的几乎相同。所以,我想问上面同样的问题。你能给我一些关于make_tuple(first(),funcs()...)的参考吗?
  • @Sungmin:Here is online docstd::make_tuple。看看它,了解它的用法!
【解决方案3】:

@Andy 的修复方法有效,但您可以做很多比这更简单的方法,无需实现重载或辅助函数:

#include <iostream>
#include <tuple>

template<typename... Args>
auto tuple_from_funs(Args&&... args) -> std::tuple<decltype(args())...>{
    return std::make_tuple(args()...);
}

int f() { return 1; }
char g() { return '2'; }
std::string h() { return "jorge"; }

int main() {
    auto tup = tuple_from_funs(f, g, h);
    std::cout << std::get<0>(tup) << ", " << std::get<1>(tup) << ", " << std::get<2>(tup) << std::endl;
}

演示here.

【讨论】:

  • 非常感谢。但是,我并不完全了解。它是如何工作的?你能给我一些关于std::make_tuple(args()...)这一行的参考吗?
  • std::make_tuple 只是一个函数,它接受一些可变模板参数并返回一个包含所有这些参数的元组。至于args()...,它的基本意思是“对这个参数包中的每个参数应用调用运算符,并展开它”。和arg0(), arg1(), arg....一样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-28
  • 2018-06-12
  • 1970-01-01
  • 1970-01-01
  • 2020-08-16
  • 1970-01-01
相关资源
最近更新 更多