#include #include #include #include #include #include // // struct contained models a type that contains a type (for example std::pair) // arrays are contained by value, and have to be treated as a special case: // template struct contained { // define our typedefs first, arrays are stored by value // so value_type is not the same as result_type: typedef typename boost::call_traits::param_type param_type; typedef typename boost::call_traits::reference reference; typedef typename boost::call_traits::const_reference const_reference; typedef T value_type; typedef typename boost::call_traits::value_type result_type; // stored value: value_type v_; // constructors: contained() {} contained(param_type p) : v_(p){} // return byval: result_type value() { return v_; } // return by_ref: reference get() { return v_; } const_reference const_get()const { return v_; } // pass value: void call(param_type p){} }; template struct contained { typedef typename boost::call_traits::param_type param_type; typedef typename boost::call_traits::reference reference; typedef typename boost::call_traits::const_reference const_reference; typedef T value_type[N]; typedef typename boost::call_traits::value_type result_type; value_type v_; contained(param_type p) { std::copy(p, p+N, v_); } // return byval: result_type value() { return v_; } // return by_ref: reference get() { return v_; } const_reference const_get()const { return v_; } void call(param_type p){} }; template contained::value_type> wrap(const T& t) { return contained::value_type>(t); } template std::pair< typename boost::call_traits::value_type, typename boost::call_traits::value_type> make_pair(const T1& t1, const T2& t2) { return std::pair< typename boost::call_traits::value_type, typename boost::call_traits::value_type>(t1, t2); } using namespace std; // // struct checker: // verifies behaviour of contained example: // template struct checker { typedef typename boost::call_traits::param_type param_type; void operator()(param_type); }; template void checker::operator()(param_type p) { T t(p); contained c(t); cout << "checking contained<" << typeid(T).name() << ">..." << endl; assert(t == c.value()); assert(t == c.get()); assert(t == c.const_get()); cout << "typeof contained<" << typeid(T).name() << ">::v_ is: " << typeid(&contained::v_).name() << endl; cout << "typeof contained<" << typeid(T).name() << ">::value() is: " << typeid(&contained::value).name() << endl; cout << "typeof contained<" << typeid(T).name() << ">::get() is: " << typeid(&contained::get).name() << endl; cout << "typeof contained<" << typeid(T).name() << ">::const_get() is: " << typeid(&contained::const_get).name() << endl; cout << "typeof contained<" << typeid(T).name() << ">::call() is: " << typeid(&contained::call).name() << endl; cout << endl; } template struct checker { typedef typename boost::call_traits::param_type param_type; void operator()(param_type); }; template void checker::operator()(param_type t) { contained c(t); cout << "checking contained<" << typeid(T[N]).name() << ">..." << endl; unsigned int i = 0; for(i = 0; i < N; ++i) assert(t[i] == c.value()[i]); for(i = 0; i < N; ++i) assert(t[i] == c.get()[i]); for(i = 0; i < N; ++i) assert(t[i] == c.const_get()[i]); cout << "typeof contained<" << typeid(T[N]).name() << ">::v_ is: " << typeid(&contained::v_).name() << endl; cout << "typeof contained<" << typeid(T[N]).name() << ">::value is: " << typeid(&contained::value).name() << endl; cout << "typeof contained<" << typeid(T[N]).name() << ">::get is: " << typeid(&contained::get).name() << endl; cout << "typeof contained<" << typeid(T[N]).name() << ">::const_get is: " << typeid(&contained::const_get).name() << endl; cout << "typeof contained<" << typeid(T[N]).name() << ">::call is: " << typeid(&contained::call).name() << endl; cout << endl; } // // check_wrap: // verifies behaviour of "wrap": // template void check_wrap(T c, U u, const V& v) { cout << "checking contained<" << typeid(T::value_type).name() << ">..." << endl; assert(c.get() == u); cout << "typeof deduced argument was: " << typeid(V).name() << endl; cout << "typeof deduced parameter after adjustment was: " << typeid(v).name() << endl; cout << "typeof contained<" << typeid(T::value_type).name() << ">::v_ is: " << typeid(&T::v_).name() << endl; cout << "typeof contained<" << typeid(T::value_type).name() << ">::value is: " << typeid(&T::value).name() << endl; cout << "typeof contained<" << typeid(T::value_type).name() << ">::get is: " << typeid(&T::get).name() << endl; cout << "typeof contained<" << typeid(T::value_type).name() << ">::const_get is: " << typeid(&T::const_get).name() << endl; cout << "typeof contained<" << typeid(T::value_type).name() << ">::call is: " << typeid(&T::call).name() << endl; cout << endl; } // // check_make_pair: // verifies behaviour of "make_pair": // template void check_make_pair(T c, U u, V v) { cout << "checking std::pair<" << typeid(c.first).name() << ", " << typeid(c.second).name() << ">..." << endl; assert(c.first == u); assert(c.second == v); cout << endl; } struct UDT { int i_; UDT() : i_(2){} bool operator == (const UDT& v){ return v.i_ == i_; } }; int main() { checker c1; UDT u; c1(u); checker c2; int i = 2; c2(i); int* pi = &i; checker c3; c3(pi); checker c4; c4(i); checker c5; c5(i); int a[2] = {1,2}; checker c6; c6(a); check_wrap(wrap(2), 2, 2); const char ca[4] = "abc"; // compiler can't deduce this for some reason: //check_wrap(wrap(ca), ca, ca); check_wrap(wrap(a), a, a); check_make_pair(::make_pair(a, a), a, a); return 0; }