【发布时间】:2017-12-24 12:50:16
【问题描述】:
我想传递模板函数,就好像它们是通用 lambda 一样,但这不起作用。
#include <iostream>
#include <vector>
#include <tuple>
#include <string>
#include <utility>
// for_each with std::tuple
// (from https://stackoverflow.com/a/6894436/1583122)
template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
for_each(std::tuple<Tp...> &, FuncT)
{}
template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
for_each(std::tuple<Tp...>& t, FuncT f) {
f(std::get<I>(t));
for_each<I + 1, FuncT, Tp...>(t, f);
}
// my code
template<class T> auto
print(const std::vector<T>& v) -> void {
for (const auto& e : v) {
std::cout << e << "\t";
}
}
struct print_wrapper {
template<class T>
auto operator()(const std::vector<T>& v) {
print(v);
}
};
auto print_gen_lambda = [](const auto& v){ print(v); };
auto print_gen_lambda_2 = []<class T>(const std::vector<T>& v){ print(v); }; // proposal P0428R1, gcc extension in c++14/c++17
int main() {
std::tuple<std::vector<int>,std::vector<double>,std::vector<std::string>> t = { {42,43},{3.14,2.7},{"Hello","World"}};
for_each(t, print); // case 1: error: template argument deduction/substitution failed: couldn't deduce template parameter 'FuncT'
for_each(t, print_wrapper()); // case 2: ok
for_each(t, print_gen_lambda); // case 3: ok
for_each(t, print_gen_lambda_2); // case 4: ok
}
请注意,情况 2 和 4 是严格等价的。案例 3 更普遍但不受限制(这对我来说是个问题)。我认为情况 1 应该被语言等同于情况 2 和 4,但事实并非如此。
- 是否有建议将模板函数隐式转换为通用约束 lambda(案例 2/4)?如果不是,是否存在阻止这样做的基本语言原因?
- 到目前为止,我必须使用案例2,这很麻烦。
- 案例 4:不符合 c++14,即使在 c++20 中应该是标准的,但仍然不完美(冗长,因为您创建了一个基本上不添加任何信息的 lambda)。
- 案例 3:不受约束,但我依赖(此处未显示)使用非“向量”参数调用“打印”的替换失败(P0428R1 提到了这个问题)。所以我想次要问题是“我可以用一些 enable_if 技巧来约束一个通用的 lambda 吗?”
在 C++14/17/20 中,是否有一种非常简洁的方式来实现从案例 1 到案例 2 的转换?我什至对宏黑客持开放态度。
【问题讨论】:
-
对于任何想知道的人来说,问题源于
print实际上没有命名函数。 -
是的。诀窍是模板函数不是类型,而具有模板成员函数的非模板类只是普通类型。
标签: c++ lambda c++14 enable-if