gpt4 book ai didi

c++ - 根据可调用的签名自动选择一元与二进制 std::transform 函数重载

转载 作者:行者123 更新时间:2023-12-01 12:44:07 25 4
gpt4 key购买 nike

std::transform提供采用一元(一个参数)或二元(两个参数)可调用操作(通常为 lambda)的重载。

我想将我想要的可调用对象作为参数传递给父函数,并使用编译时(例如模板元编程)方法来自动选择 std::transform 中的哪一个根据传递的可调用对象是否具有带一或两个参数的函数签名,使用重载。

这是用(尚未工作)代码表达的所需方法:

#include <algorithm>

auto UnaryOp = [](const auto& src) { return src; }; // simple copy
auto BinaryOp = [](const auto& src1, const auto& src2) {return src1 + src2; }; // accumulate

auto GenericTransformer = [](auto src, auto dst, auto operation) { // operation is unary OR binary

/* unrelated code */

// need to chose this one:
std::transform(src.begin(), src.end(), dst.begin(), operation);
// or this one:
std::transform(src.begin(), src.end(), dst.begin(), dst.begin(), operation);
// depending on whether unary or binary operation is passed in 'operation' argument

/* unrelated code */

};

int main() {
std::vector<int> source_vec(100);
std::vector<int> dest_vec(100);
GenericTransformer(source_vec, dest_vec, UnaryOp); // i.e. copy source to destination
GenericTransformer(source_vec, dest_vec, BinaryOp); // i.e. accumulate source into destination
}

在这里,我定义了两个 lambda 操作——一个一元和一个二元( UnaryOpBinaryOp)——它们被传递给 GenericTransformer()来自 main() .

GenericTransformer() ,我可以使用什么编译时魔法来自动选择两者中的哪一个 std::transform()根据 operation 的函数签名进行调用争论?

注意:这是出于示例目的的简化案例。我宁愿不必拆分 GenericTransformer()分成两个独立的函数(一元函数和二进制函数),因为这会导致此处未显示的大量代码重复。坚持 DRY 理念!

最佳答案

使用 C++17,您可以混合使用 if constexpr std::is_invocable :

if constexpr (std::is_invocable_v<
decltype(operation), decltype(*src.begin())>) {
std::transform(src.begin(), src.end(), dst.begin(), operation);
}
else {
std::transform(src.begin(), src.end(), dst.begin(), dst.begin(), operation);
}

您还可以检查 operation在第二种情况下有效,但这需要额外的 else分支以避免在(两个分支都无效)时消除编译时错误,这将需要一些 always_false shenanigan .

关于c++ - 根据可调用的签名自动选择一元与二进制 std::transform 函数重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59534243/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com