如何直接使用std::get而不是Lambda函数在std::transform中?

3

我有一个 std::vector,其中包含多个 std::tuple

std::vector<std::tuple<int,int>> vt;

我可以使用算法std::transform将向量的内容转换为另一个向量,如下所示:

std::vector<int> vi(vt.size());

std::transform( vt.begin(), vt.end(), vi.begin(), [](auto &v) -> int {
    return std::get<0>(v);
} );   

当然,我也可以使用一个函数:

当然,我也可以使用一个函数:

int myget(const std::tuple<int,int>& t)
{
    return std::get<0>(t);
}

std::vector<int> vi(vt.size());
std::transform( vt.begin(), vt.end(), vi.begin(), myget );


但是,我们是否可以直接在std::transform的实际参数中使用std::get呢?

我的意思是像这样:

std::transform( vt.begin(), vt.end(), vi.begin(), std::get<0, ??? > );

可能需要一些复杂的语法来获取指向已实例化的std::get模板函数实例的指针,并将此指针作为可调用对象传递给std::transform。如果找到了这样的方法,那么肯定会有一种成就感,并且成功地遍历了C++极其复杂的语法,值得自我表扬。但是不要误以为你已经完成了任何实质性的事情,因为最终几乎可以确定编译器将生成实质上相同的代码,而你所做的只是编写了一系列难以理解的标点符号流。 - Sam Varshavchik
1个回答

4

是的,这是可能的,但我不建议这样做。因为std::get有多个重载版本,你需要进行static_cast来选择正确的版本。

static_cast<int&(*)(std::tuple<int, int>&)>(&std::get<0, int, int>)

重复模板参数两次看起来很不好看,如果你想要类型转换具有通用性,则需要写很长的代码。

相反,为了缩短Lambda表达式的长度,你可以省略-> int部分,因为返回类型会自动推断:

std::transform( vt.begin(), vt.end(), vi.begin(), [](auto &v) {
    return std::get<0>(v);
} );

有一天,我们也许可以这样写:
std::transform(vt.begin(), vt.end(), vi.begin(), [](auto &v) => std::get<0>(v));

1
根据P0573R2,std::transform(vt.begin(), vt.end(), vi.begin(), [](v) => std::get<0>(v)); - yumetodo
@yumetodo 你说得没错,但这是我的观点:我不喜欢不指定类型 :) - Rakete1111
1
有人能告诉我这个答案哪里出了问题吗?因为我会认为这个踩是有道理的。谢谢 :) - Rakete1111
@Rakete1111,你可能被点踩了,因为这个问题是重复的(已关闭)。 - Rabbid76

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接