【问题标题】:Filling a std::tuple填充 std::tuple
【发布时间】:2013-12-28 16:28:51
【问题描述】:

我有一个看起来像这样的重载函数:

template<typename T>
T getColumn(size_t i);

template<>
std::string getColumn<std::string>(size_t i) {
    if(i == 0)
        return "first";
    else
        return "other";
}

template<>
int getColumn<int>(size_t i) {
    return i*10;
}

// ...

现在我要实现这个功能

template<typename... Values>
std::tuple<Values...> getColumns();

它创建一个元组(用于返回值)并为元组的每个元素调用getColumn(将返回值保存在该元素中),其中i 是元素的位置。生成getColumn 的返回值的代码被简化(实际上它是从数据库中获取值)。

但我不知道该怎么做。

我最好的尝试是使用 boost::fusion::for_each,但我无法将 i 交给 getColumn

另一个尝试是使用 boost::fusion 中的迭代器,但这也没有用:

namespace fusion = boost::fusion;
tuple<Values...> t;
auto it = fusion::begin(t);
while(it != fusion::end(t)) {
    getColumn(distance(fusion::begin(t), it), fusion::deref(it));
    it = fusion::next(it); // error: assignment not allowed
}

如何使用i 的正确值为Values... 中的每个类型调用getColumn,并将结果保存在std::tuple 中?

【问题讨论】:

    标签: c++ tuples variadic-templates boost-fusion


    【解决方案1】:

    您需要将参数包的每个元素映射到其在包内的索引 - 这是“索引序列技巧”的典型用例:

    template <int... I> struct index_sequence {};
    template <int N, int... I>
    struct make_index_sequence : make_index_sequence<N-1,N-1,I...> {};
    template <int... I>
    struct make_index_sequence<0, I...> : index_sequence<I...> {};
    
    template<typename... Values, int... I>
    auto getColumns(index_sequence<I...>) ->
      decltype(std::make_tuple(getColumn<Values>(I)...)) {
        return std::make_tuple(getColumn<Values>(I)...);
    }
    
    template<typename... Values>
    auto getColumns() ->
      decltype(getColumns<Values...>(make_index_sequence<sizeof...(Values)>())) {
        return getColumns<Values...>(make_index_sequence<sizeof...(Values)>());
    }
    

    Live demo at Coliru.

    【讨论】:

    • 一个很好的副作用是辅助函数也很有用。但是可以通过默认参数消除它,(或换句话说)使辅助函数成为唯一的函数吗?
    • @Yakk 我认为不是:中间类型是推断索引所必需的。没有指定为参数包提供默认值的语法(参见 [temp.param]/1)。
    • 能否推导出Values...,用于产生第二个参数的默认参数,然后从中推导出Is...?可能不会:即使它已编译,我也想对标准进行深入研究以确保它不是意外扩展。
    • 正是我需要的,谢谢!辅助功能对我来说不是问题。我已经将这些功能集成到一个类中,只是将助手设为私有。请注意成员函数上的 decltype,因为 GCC 有一个错误,因此您需要显式使用 this-&gt; (gcc.gnu.org/bugzilla/show_bug.cgi?id=57543)。 Clang 没有这个问题。
    【解决方案2】:

    也许auto:

    template<typename... Values>
    auto getColumns() -> decltype(std::make_tuple(getColumns<Values>()...))
    {
        return std::make_tuple(getColumns<Values>()...);
    }
    

    在 C++14 中,您可以省略 -&gt; decltype... 部分,因为它将从函数体中推导出来。

    【讨论】:

    • 需要索引:OP 想调用GetColumn&lt;T&gt;(i)...
    猜你喜欢
    • 2019-06-15
    • 2017-12-23
    • 1970-01-01
    • 2019-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多