1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // cpp-next_bug.hpp |
3 | // |
4 | // Copyright 2012 Eric Niebler. Distributed under the Boost |
5 | // Software License, Version 1.0. (See accompanying file |
6 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
7 | |
8 | #include <vector> |
9 | #include <boost/proto/proto.hpp> |
10 | #include <boost/test/unit_test.hpp> |
11 | namespace mpl = boost::mpl; |
12 | namespace proto = boost::proto; |
13 | using proto::_; |
14 | |
15 | namespace linear_algebra |
16 | { |
17 | // A trait that returns true only for std::vector |
18 | template<typename T> |
19 | struct is_std_vector |
20 | : mpl::false_ |
21 | {}; |
22 | |
23 | template<typename T, typename A> |
24 | struct is_std_vector<std::vector<T, A> > |
25 | : mpl::true_ |
26 | {}; |
27 | |
28 | // A type used as a domain for linear algebra expressions |
29 | struct linear_algebra_domain |
30 | : proto::domain<> |
31 | {}; |
32 | |
33 | // Define all the operator overloads for combining std::vectors |
34 | BOOST_PROTO_DEFINE_OPERATORS(is_std_vector, linear_algebra_domain) |
35 | |
36 | // Take any expression and turn each node |
37 | // into a subscript expression, using the |
38 | // state as the RHS. |
39 | struct Distribute |
40 | : proto::or_< |
41 | proto::when<proto::terminal<_>, proto::_make_subscript(_, proto::_state)> |
42 | , proto::plus<Distribute, Distribute> |
43 | > |
44 | {}; |
45 | |
46 | struct Optimize |
47 | : proto::or_< |
48 | proto::when< |
49 | proto::subscript<Distribute, proto::terminal<_> >, |
50 | Distribute(proto::_left, proto::_right) |
51 | > |
52 | , proto::plus<Optimize, Optimize> |
53 | , proto::terminal<_> |
54 | > |
55 | {}; |
56 | } |
57 | |
58 | static const int celems = 4; |
59 | static int const value[celems] = {1,2,3,4}; |
60 | std::vector<int> A(value, value+celems), B(A); |
61 | |
62 | void test1() |
63 | { |
64 | using namespace linear_algebra; |
65 | proto::_default<> eval; |
66 | BOOST_CHECK_EQUAL(8, eval(Optimize()((A + B)[3]))); |
67 | } |
68 | |
69 | using namespace boost::unit_test; |
70 | /////////////////////////////////////////////////////////////////////////////// |
71 | // init_unit_test_suite |
72 | // |
73 | test_suite* init_unit_test_suite( int argc, char* argv[] ) |
74 | { |
75 | test_suite *test = BOOST_TEST_SUITE("test for a problem reported on the cpp-next.com blog" ); |
76 | |
77 | test->add(BOOST_TEST_CASE(&test1)); |
78 | |
79 | return test; |
80 | } |
81 | |