实现函数模板填充多维对象
Implement function template to fill multi-dimensional objects
在 C++ 中填充多维对象(数组、嵌套标准容器等)一直让我很烦。通常使用嵌套循环。例如,要用值 v
填充 3 维对象 obj
,您可以这样写
for (auto& x : obj) {
for (auto& y : x) {
for (auto& z : y) {
z = v;
}
}
}
这样的循环是代码噪音,写起来很乏味,也妨碍代码阅读。我正在考虑编写一个函数模板来执行填充。理想情况下,有了这样的函数模板,你应该可以写出类似
的东西
fill(obj, v);
有什么想法吗?
目前,我有一个功能模板make_multi()
来制作多维对象。所以你可以做
// assuming `obj` is a 3x3x3 nested `std::vector`
obj = make_multi<std::vector>(v, 3, 3, 3);
除了代码比理想情况更多之外,此解决方案还是性能噩梦。最终,我必须寻找更好的方法。
你可以写一个扁平化的foreach:
namespace detail {
template <typename Range, typename Func>
constexpr auto flat_foreach(Range&& r, Func& f, int)
-> decltype(void(f(std::forward<Range>(r)))) {f(std::forward<Range>(r));}
template <typename Range, typename Func>
constexpr void flat_foreach(Range&& r, Func& f...) {
for (auto&& i : r)
flat_foreach(std::forward<decltype(i)>(i), f, 0);
}
}
template <typename Range, typename Func>
constexpr void flat_foreach(Range&& r, Func f)
{detail::flat_foreach(std::forward<Range>(r), f, 0);}
Demo。这是 non-greedy 方法,将范围传递给尽可能浅的给定函数。
这是 的贪婪对应:
namespace detail {
using std::begin;
using std::end;
template<typename Elem, typename Func>
constexpr void flat_foreach(Elem&& e, Func& f, long) {
f(std::forward<Elem>(e));
}
template<typename Range, typename Func>
constexpr auto flat_foreach(Range&& r, Func& f, int)
-> decltype(begin(r), void(end(r))) {
for (auto&& i : r) {
flat_foreach(std::forward<decltype(i)>(i), f, 0);
}
}
}
template<typename Range, typename Func>
constexpr void flat_foreach(Range&& r, Func f) {
detail::flat_foreach(std::forward<Range>(r), f, 0);
}
这种方法的一般优点是可以为 f
.
传入一个 generic lambda/functor
在 C++ 中填充多维对象(数组、嵌套标准容器等)一直让我很烦。通常使用嵌套循环。例如,要用值 v
填充 3 维对象 obj
,您可以这样写
for (auto& x : obj) {
for (auto& y : x) {
for (auto& z : y) {
z = v;
}
}
}
这样的循环是代码噪音,写起来很乏味,也妨碍代码阅读。我正在考虑编写一个函数模板来执行填充。理想情况下,有了这样的函数模板,你应该可以写出类似
的东西fill(obj, v);
有什么想法吗?
目前,我有一个功能模板make_multi()
来制作多维对象。所以你可以做
// assuming `obj` is a 3x3x3 nested `std::vector`
obj = make_multi<std::vector>(v, 3, 3, 3);
除了代码比理想情况更多之外,此解决方案还是性能噩梦。最终,我必须寻找更好的方法。
你可以写一个扁平化的foreach:
namespace detail {
template <typename Range, typename Func>
constexpr auto flat_foreach(Range&& r, Func& f, int)
-> decltype(void(f(std::forward<Range>(r)))) {f(std::forward<Range>(r));}
template <typename Range, typename Func>
constexpr void flat_foreach(Range&& r, Func& f...) {
for (auto&& i : r)
flat_foreach(std::forward<decltype(i)>(i), f, 0);
}
}
template <typename Range, typename Func>
constexpr void flat_foreach(Range&& r, Func f)
{detail::flat_foreach(std::forward<Range>(r), f, 0);}
Demo。这是 non-greedy 方法,将范围传递给尽可能浅的给定函数。
这是
namespace detail {
using std::begin;
using std::end;
template<typename Elem, typename Func>
constexpr void flat_foreach(Elem&& e, Func& f, long) {
f(std::forward<Elem>(e));
}
template<typename Range, typename Func>
constexpr auto flat_foreach(Range&& r, Func& f, int)
-> decltype(begin(r), void(end(r))) {
for (auto&& i : r) {
flat_foreach(std::forward<decltype(i)>(i), f, 0);
}
}
}
template<typename Range, typename Func>
constexpr void flat_foreach(Range&& r, Func f) {
detail::flat_foreach(std::forward<Range>(r), f, 0);
}
这种方法的一般优点是可以为 f
.