/* * $Rev: 6060 $ * Author: Jesse Perla (c) 2010 * Use, modification and distribution are subject to the * Boost Software License, Version 1.0. (See accompanying file * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #pragma once #include #include #include #include #include #include #include #include #ifndef BOOST_ASSIGN_MAX_SIZE # define BOOST_ASSIGN_MAX_SIZE 20 #endif namespace boost{ namespace numeric { namespace ublas { //Using dispatching to ensure no assignment happens with boost::mpl::void_ types. template struct assign_helper; template struct assign_helper { template //Assigns a member of a vector to t1 void assign(T& t1, const Vector& v) { t1 = v[Index]; //Assumes assignable between types. Accessing the static index within the vector expression. } }; template struct assign_helper { template void assign(T1& t1, const Vector& t2) { //Does nothing. This is an mpl::void_ } }; //Object used to tie the references to the objects prior to assignment. template struct tie_helper { //Generate something like: //T0& t0_; //T1& t1_; #define UBLAS_ASSIGN_DATA_MEMBER(z, n, unused) T##n & t##n##_; \ BOOST_PP_REPEAT(BOOST_ASSIGN_MAX_SIZE, UBLAS_ASSIGN_DATA_MEMBER, ~) //Constructor stores references. Is this kosher for creating with boost::mpl::void_ objects as default arguments then keeping references to them? Seems to compile. //Generating something like: //tie_helper(T0& t0 = T0(), T1& t1 = T1(), T2& t2 = T2()) : t0_(t0), t1_(t1), t2_(t2) {}; #define UBLAS_ASSIGN_CONSTRUCTOR_ARGUMENTS(z, n, unused) BOOST_PP_COMMA_IF(n) T##n & t##n = T##n () #define UBLAS_ASSIGN_CONSTRUCTOR_INITIALIZATION(z, n, unused) BOOST_PP_COMMA_IF(n) t##n##_ ( t##n ) tie_helper(BOOST_PP_REPEAT(BOOST_ASSIGN_MAX_SIZE, UBLAS_ASSIGN_CONSTRUCTOR_ARGUMENTS, ~)) : BOOST_PP_REPEAT(BOOST_ASSIGN_MAX_SIZE, UBLAS_ASSIGN_CONSTRUCTOR_INITIALIZATION, ~) {}; //Assignment template void operator= (const ublas::vector_expression& v) { //Instead of assigning directly, this is using the assign_helper dispatcher to prevent assignment for boost::mpl::void_ types. //Generate something like: //assign_helper().assign(t0_, v(), 0); //assign_helper().assign(t1_, v(), 1); #define UBLAS_ASSIGN_ASSIGN_VALUE(z, n, unused) assign_helper().assign(t##n##_, v()); \ BOOST_PP_REPEAT(BOOST_ASSIGN_MAX_SIZE, UBLAS_ASSIGN_ASSIGN_VALUE, ~) } }; //Generate constuction functions such as: //template //tie_helper tie(T0& t0, T1& t1) //{ // return tie_helper(t0, t1); //} #define UBLAS_ASSIGN_HELPER(z, n, unused) \ template \ tie_helper tie(BOOST_PP_ENUM_BINARY_PARAMS(n, T, & t)) \ { \ return tie_helper(BOOST_PP_ENUM_PARAMS(n, t)); \ } //Vertical repetition #define BOOST_PP_LOCAL_MACRO(n) UBLAS_ASSIGN_HELPER(~, n, ~) #define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_SIZE) #include BOOST_PP_LOCAL_ITERATE() } } } //Remove local macros #undef UBLAS_ASSIGN_DATA_MEMBER #undef UBLAS_ASSIGN_CONSTRUCTOR_ARGUMENTS #undef UBLAS_ASSIGN_CONSTRUCTOR_INITIALIZATION #undef UBLAS_ASSIGN_ASSIGN_VALUE #undef UBLAS_ASSIGN_HELPER