Đây là giải pháp thay thế được lấy cảm hứng từ Luc Touraille's answer.
Phiên bản này được thực hiện bằng cách sử dụng Metafunction classes thay vì chức năng cho phép static_for_each
được gọi ngay cả bên ngoài phạm vi chức năng (hữu ích nếu công việc phải hoàn toàn được thực hiện tại compiletime).
Ngoài ra, nó còn mang lại nhiều tương tác hơn nhờ các typaief first
và last
, cho phép lấy thông tin ra khỏi vòng lặp nếu cần, giống như cách return
hoạt động cho một chức năng.
Bạn cũng có thể truy cập kết quả lặp lại trước đó trong mỗi lần lặp lại nhờ tham số mẫu thứ hai Previous
được chuyển đến lớp metafunction F
.
Cuối cùng, bạn có thể cung cấp dữ liệu cho quy trình vòng lặp sử dụng tham số mẫu Initial
, nó sẽ được cung cấp dưới dạng giá trị của tham số Previous
của lần lặp đầu tiên.
# include <boost/mpl/begin_end.hpp>
# include <boost/mpl/next_prior.hpp>
# include <boost/mpl/apply.hpp>
namespace detail_static_for_each
{
// Loop
template<typename Begin, typename End, typename F, typename Previous>
struct static_for_each
{
private:
typedef typename Begin::type current_type;
public:
typedef typename boost::mpl::apply<F, current_type, Previous>::type first;
typedef typename static_for_each<typename boost::mpl::next<Begin>::type, End, F, first>::last last;
};
// End of loop
template<typename End, typename F, typename Last>
struct static_for_each<End, End, F, Last>
{
public:
typedef Last first;
typedef Last last;
};
} // namespace detail_static_for_each
// Public interface
template<typename Sequence, typename F, typename Initial = void>
struct static_for_each
{
private:
typedef typename boost::mpl::begin<Sequence>::type begin;
typedef typename boost::mpl::end<Sequence>::type end;
typedef typename detail_static_for_each::static_for_each<begin, end, F, Initial> loop;
public:
typedef typename loop::first first;
typedef typename loop::last last;
};
Dưới đây là một ví dụ đơn giản mà cả cho và lấy dữ liệu:
# include <iostream>
# include <boost/type_traits/is_same.hpp>
# include <boost/mpl/if.hpp>
# include <boost/mpl/vector.hpp>
# include "static_for_each.hpp"
struct is_there_a_float
{
template<typename currentItem, typename PreviousIterationType>
struct apply
{
typedef typename boost::mpl::if_< PreviousIterationType,
PreviousIterationType,
boost::is_same<float, currentItem> >::type type;
};
};
struct test
{
typedef boost::mpl::vector< char, long, long, double, float, int, char > sequence;
typedef static_for_each<sequence, is_there_a_float, boost::false_type>::last found;
};
int main(void)
{
std::cout << std::boolalpha << test::found::value << std::endl;
return (0);
}
Những tính năng này làm cho việc sử dụng các static_for_each
hơn tương tự như việc sử dụng các vòng thi chung (while
, for
, BOOST_FOREACH .. .) khi bạn có thể tương tác trực tiếp hơn với vòng lặp.
Hướng dẫn rất hữu ích tại đây. Cảm ơn. – Marcin