这里我首先介绍模板函数over(vec, f)
的两个变体。
两个版本都迭代一个类似矢量的对象,并为每个元素调用一个函数对象。
一个版本使用两个参数调用函数对象 - 元素引用和索引 - 第二个只使用元素引用。
这个想法是让编译器选择与传入的lambda匹配的版本,这样用户就可以在lambda签名中表达意图,而不必选择不同名称的自由函数。
这是代码:
#include <vector>
#include <iostream>
template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type;
template<class Vector, class F>
auto over(Vector &&vec, F &&f)
-> void_t<decltype(f(vec.operator[](std::declval<std::size_t>()), std::declval<std::size_t>()))>
{
const auto size = vec.size();
for (std::size_t i = 0; i < size; ++i) {
f(vec[i], i);
}
}
template<class Vector, class F>
auto over(Vector &&vec, F &&f)
-> void_t<decltype(f(*vec.begin()))>
{
for (auto &&x : vec) {
f(x);
}
}
int main() {
std::vector<float> vf = {1.0, 1.1, 1.2};
std::cout << "two-argument form:\n";
over(vf, [](auto &&val, auto &&index) {
std::cout << index << " : " << val << std::endl;
});
std::cout << "\none-argument form:\n";
over(vf, [](auto &&val) {
std::cout << val << std::endl;
});
}
问题:
您将看到void_t<>
返回类型生成器中的子句知道该函数的实现。我对此感到不满:
a)它在界面中泄露了实现细节,
b)它不是干的。
有没有更好的方法来实现这一目标:
a)允许在不更改模板启用程序
的情况下更改实现b)看起来我的狗在我的键盘上打得不合适?
答案 0 :(得分:2)
对于这个例子,避免“重复”将比重复本身更多的工作/复杂性,但基本的想法是计算函数的优点,然后适当地调度。这里讨论一个非常类似的问题:Call function with part of variadic arguments。使用metricName
的实现,你可以实现一个名为dispatch的函数(我在回答这个问题时称之为foo):
MyEvaluator
此答案也符合14条要求。实例:http://coliru.stacked-crooked.com/a/14750cef6b735d7e。
编辑:此方法不适用于通用lambdas。所以另一种方法是以这种方式实现调度:
Evaluator
答案 1 :(得分:1)
在C ++ 17中,您可以使用基于std::is_invocable
的SFINAE,类似于:
template <class Vector, class F>
std::enable_if_t<std::is_invocable<F,
typename Vector::value_type,
std::size_t>::value>
over(const Vector& vec, F&& f)
{
const auto size = vec.size();
for (std::size_t i = 0; i < size; ++i) {
f(vec[i], i);
}
}
template <class Vector, class F>
std::enable_if_t<std::is_invocable<F, typename Vector::value_type>::value>
over(const Vector& vec, F&& f)
{
const auto size = vec.size();
for (const auto& e : vec) {
f(e);
}
}
答案 2 :(得分:0)
好的,这是我的第一次认真尝试。
有没有比这更好的东西?
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let firstViewController = storyboard.instantiateViewController(withIdentifier: "FirstViewController") as? FirstViewController
let secondViewController = storyboard.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController
let thirdViewController = storyboard.instantiateViewController(withIdentifier: "ThirdViewController") as? ThirdViewController
self.navigationController?.setViewControllers([firstViewController,secondViewController,thirdViewController], animated: false)