Ticket #4436: tie.hpp

File tie.hpp, 3.9 KB (added by anonymous, 12 years ago)
Line 
1/*
2 * $Rev: 6074 $
3 * Author: Jesse Perla (c) 2010
4 * Use, modification and distribution are subject to the
5 * Boost 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
9#pragma once
10#include <boost/numeric/ublas/vector_expression.hpp>
11#include <boost/preprocessor/repetition/enum_params.hpp>
12#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
13#include <boost/preprocessor/repetition/enum_binary_params.hpp>
14#include <boost/preprocessor/repetition.hpp>
15#include <boost/preprocessor/repetition/repeat_from_to.hpp>
16#include <boost/preprocessor/iteration/local.hpp>
17#include <boost/preprocessor/punctuation/comma_if.hpp>
18
19#ifndef BOOST_ASSIGN_MAX_SIZE
20# define BOOST_ASSIGN_MAX_SIZE 20
21#endif
22
23namespace boost{ namespace numeric { namespace ublas {
24
25 //Using dispatching to ensure no assignment happens with boost::mpl::void_ types.
26 template<std::size_t Index, typename T> struct assign_helper;
27 template<std::size_t Index, typename T> struct assign_helper
28 {
29 template<typename Vector> //Assigns a member of a vector to t1
30 void assign(T& t1, const Vector& v)
31 {
32 t1 = v[Index]; //Assumes assignable between types. Accessing the static index within the vector expression.
33 }
34 };
35
36 template<std::size_t Index>
37 struct assign_helper<Index, boost::mpl::void_>
38 {
39 template<typename T1, typename Vector>
40 void assign(T1& t1, const Vector& t2)
41 { //Does nothing. This is an mpl::void_
42 }
43 };
44
45 //Object used to tie the references to the objects prior to assignment.
46 template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_ASSIGN_MAX_SIZE, typename T, boost::mpl::void_)>
47 struct tie_helper
48 {
49 //Generate something like:
50 //T0& t0_;
51 //T1& t1_;
52
53#define UBLAS_ASSIGN_DATA_MEMBER(z, n, unused) T##n & t##n##_; \
54
55 BOOST_PP_REPEAT(BOOST_ASSIGN_MAX_SIZE, UBLAS_ASSIGN_DATA_MEMBER, ~)
56
57 //Constructor stores references. Is this kosher for creating with boost::mpl::void_ objects as default arguments then keeping references to them? Seems to compile.
58 //Generating something like:
59 //tie_helper(T0& t0 = T0(), T1& t1 = T1(), T2& t2 = T2()) : t0_(t0), t1_(t1), t2_(t2) {};
60
61#define UBLAS_ASSIGN_CONSTRUCTOR_ARGUMENTS(z, n, unused) BOOST_PP_COMMA_IF(n) T##n & t##n = T##n ()
62#define UBLAS_ASSIGN_CONSTRUCTOR_INITIALIZATION(z, n, unused) BOOST_PP_COMMA_IF(n) t##n##_ ( t##n )
63
64 tie_helper(BOOST_PP_REPEAT(BOOST_ASSIGN_MAX_SIZE, UBLAS_ASSIGN_CONSTRUCTOR_ARGUMENTS, ~)) : BOOST_PP_REPEAT(BOOST_ASSIGN_MAX_SIZE, UBLAS_ASSIGN_CONSTRUCTOR_INITIALIZATION, ~)
65 {};
66
67 //Assignment
68 template<typename VectorT>
69 void operator= (const ublas::vector_expression<VectorT>& v)
70 {
71 //Instead of assigning directly, this is using the assign_helper dispatcher to prevent assignment for boost::mpl::void_ types.
72 //Generate something like:
73 //assign_helper<T0>().assign(t0_, v(), 0);
74 //assign_helper<T1>().assign(t1_, v(), 1);
75
76#define UBLAS_ASSIGN_ASSIGN_VALUE(z, n, unused) assign_helper<n, T##n##>().assign(t##n##_, v()); \
77
78 BOOST_PP_REPEAT(BOOST_ASSIGN_MAX_SIZE, UBLAS_ASSIGN_ASSIGN_VALUE, ~)
79 }
80 };
81
82
83//Generate constuction functions such as:
84//template<typename T0, typename T1>
85//tie_helper<T0, T1> tie(T0& t0, T1& t1)
86//{
87// return tie_helper<T0, T1>(t0, t1);
88//}
89
90#define UBLAS_ASSIGN_HELPER(z, n, unused) \
91 template<BOOST_PP_ENUM_PARAMS(n, typename T)> \
92 tie_helper<BOOST_PP_ENUM_PARAMS(n, T)> tie(BOOST_PP_ENUM_BINARY_PARAMS(n, T, & t)) \
93 { \
94 return tie_helper<BOOST_PP_ENUM_PARAMS(n, T)>(BOOST_PP_ENUM_PARAMS(n, t)); \
95 }
96
97
98//Vertical repetition
99#define BOOST_PP_LOCAL_MACRO(n) UBLAS_ASSIGN_HELPER(~, n, ~)
100#define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_SIZE)
101
102#include BOOST_PP_LOCAL_ITERATE()
103
104} } }
105
106//Remove local macros
107#undef UBLAS_ASSIGN_DATA_MEMBER
108#undef UBLAS_ASSIGN_CONSTRUCTOR_ARGUMENTS
109#undef UBLAS_ASSIGN_CONSTRUCTOR_INITIALIZATION
110#undef UBLAS_ASSIGN_ASSIGN_VALUE
111#undef UBLAS_ASSIGN_HELPER