C++ lambda 的模板类型推断

C++ template type inference for lambdas

本文关键字:类型 lambda C++      更新时间:2023-10-16

假设我有这个函数:

template <typename T>
T sum(std::vector<T> const& v) {
T acc = T();
for (auto const& e : v) {
acc += e;
}
return acc;
}

这里C++只允许用向量调用这个函数,并且可以自动推断T类型参数。

有什么方法可以使用lambdas做同样的事情吗?我知道它们在语义上与函子相同,我可以很容易地在那里做到这一点,但我对内联的 lambda 感兴趣。我知道我可以这样做:

[](auto& v) { ... }

但这匹配任何内容,甚至是非矢量参数(即使主体导致编译器错误)。

在 C++20 中,我们可以在捕获列表之后指定模板参数:

auto accum = []<class T>(std::vector<T>& v) {
auto acc = T{};
for (auto const& e : v) {
acc += e;
}
return acc;
};

演示

在此期间,假设您现在只能依靠类型特征来推断value_type

auto accum = [](auto& v) {
auto acc = typename std::decay_t<decltype(v)>::value_type{};
for (auto const& e : v) {
acc += e;
}
return acc;
};

如果要强制实施特定容器,可以使用static_assert

auto accum = [](auto& v) {
using ttype = std::decay_t<decltype(v)>;
using vtype = typename ttype::value_type;
static_assert(std::is_same_v<std::vector<vtype>, ttype>);
auto acc = vtype{};
for (auto const& e : v) {
acc += e;
}
return acc;
};

例如:

int main(){
std::vector<int> v{1,2,3};
std::list<double> l{4.0,5.0,6.0};
auto accum = [](auto& v) {
auto acc = typename std::decay_t<decltype(v)>::value_type{};
for (auto const& e : v) {
acc += e;
}
return acc;
};
std::cout << accum(v) << std::endl;
std::cout << accum(l) << std::endl;
}

演示任何带有value_type的可迭代容器

带有vector类型的static_assert演示


既然您提到您没有使用 STL 容器,而是使用幻像类型,那么您有两个选择:

  • 将 typedef 添加到强类型枚举中,就像这样using value_type = PHANTOM_TYPE
  • 创建一个单独的特征类来推断value_type

    模板 结构体 SUInt { 公共: SUInt (unsigned int value) : m_value(value) { } inline unsigned int& Value () { return m_value; } 私人: 无符号的 int m_value; };

    模板 struct SUInt_traits{};

    模板 结构SUInt_traits>{ 使用 value_type = T; };

然后,您可以从 lambda 中使用它,如下所示:

auto do_a_thing = [](auto& v) {
auto acc =  typename SUInt_traits<std::decay_t<decltype(v)>>::value_type{};
// ...
};

你可以使用带有 std::accumulate 的 lambda,尽管给定一个简单的总和,实际上并不需要 lambda。