从 C++17

问题描述

我一直希望使用新的 C++17 功能,如折叠表达式和 std::apply() 来简化我拥有的一些使用 std::index_sequencestd::initializer_list 等工具的 C++11 代码对于元组的一些操作。特别是一项任务给我带来了一些麻烦:将一系列值(例如从 boost::tokenizer 对象)复制到元组我有一个可行的解决方案,它在要分配值的元组调用 std::apply(),但它仍然必须在内部使用 std::initializer_list(为简单起见,我用一个简单的向量:

#include <iostream>
#include <vector>
#include <tuple>

template<typename Tuple,typename Iterator>
size_t copy_range_to_tuple(Tuple& tup,Iterator begin,Iterator end) {
    size_t count = 0;
    auto copy = [&begin,&end,&count] (auto& value) -> bool {
        if (begin != end) {
            value = *(begin++);
            ++count;
            return true;
        } else {
            return false;
        }
    };
    std::apply([&copy](auto&... values) {
        std::initializer_list<bool>{copy(values)...};
    },tup);
    return count;
}

int main(int,char**) {
    std::tuple<int,int,int> tup;
    std::vector<int> x{4,3,2};
    std::cout << "copy count = " << copy_range_to_tuple(tup,x.begin(),x.end()) << std::endl;
    std::cout << std::get<0>(tup) << std::endl;
    std::cout << std::get<1>(tup) << std::endl;
    std::cout << std::get<2>(tup) << std::endl;
    std::cout << std::get<3>(tup) << std::endl;
    
}

输出

copy count = 3
4
3
2
0

与我的 C++11/14 代码相比,这已经是一个巨大的胜利,我的 C++11/14 代码(由于没有 std::apply())使用索引序列将迭代器匹配到不同的元组元素。但是,我仍然有一种感觉或希望,这可以通过 fold 表达式进一步简化,消除对初始化列表的需要。准确地说,我希望我可以创建一个扩展 copy(values) 的折叠表达式。这是可能的,还是现代 C++ 有其他一些技巧可以使这不那么冗长? (去掉 copy lambda 也很好,但我认为为了检查有效的迭代器,类似的事情是不可避免的。

解决方法

带有折叠表达式的版本可能如下所示:

std::tuple<int,int,int> t;
std::vector<int> v{4,3};
auto beg = v.begin();
auto end = v.end();
std::apply([&](auto&... values){
    auto getValue = [&](){ return (beg != end) ? *beg++ : 0; }; // returns 0 if range is too small
    ((values = getValue()),...);
},t);
std::cout << std::get<0>(t) << std::endl; // 4
std::cout << std::get<1>(t) << std::endl; // 3
std::cout << std::get<2>(t) << std::endl; // 0
std::cout << std::get<3>(t) << std::endl; // 0

Demo

,

我想您可以简单地使用迭代器并调用 std::apply();我是说

auto it = v.begin();

std::apply([&](auto & ... values)
          { ((it != v.end() ? values = *it++ : values),... ); },t); 

下面是一个完整的编译示例

#include <tuple>
#include <vector>
#include <iostream>

int main ()
 {
   std::tuple<int,int> t;
   std::vector<int> v{4,3,2};
   auto it = v.begin();

   std::apply([&](auto & ... values)
             { ((it != v.end() ? values = *it++ : values),t);

   std::cout << std::get<0>(t) << std::endl; // 4
   std::cout << std::get<1>(t) << std::endl; // 3
   std::cout << std::get<2>(t) << std::endl; // 2
   std::cout << std::get<3>(t) << std::endl; // 0
 }

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...