.
template <typename Xany>
struct to_string_method
{
typedef std::string (Xany::* signature) () const;
template <typename T>
struct wrapper
: public T
{
std::string to_string() const
{
return this->call(to_string_method());
}
};
struct implementation
{
template <typename T>
std::string operator() (const T& t) const
{
std::ostringstream oss;
oss << t;
return oss.str();
}
};
};
First type defines the signature of method. wrapper template class defines the method itself and implement it by calling call method.
Actually the generated class will be derived from wrapper and to_string will become a member function of it. Third type is a functional
object which must operate with containing value (convert value to std::string in this case). As a result implementation adds additional requirement for
types supported by adaptor. The ValueType will be supported by result adaptor if
Satisfies boost::any's type requirements. See Boost.Any
All methods implementations are successfully compiling with ValueType argument.
template <typename Xany>
struct from_string_method
{
typedef void (Xany::* signature) (const std::string&);
template <typename T>
struct wrapper
: public T
{
void from_string(const std::string& str)
{
this->call(from_string_method(), str);
}
};
struct implementation {
template <typename T>
void operator() (T& t, const std::string& str) const
{
std::istringstream iss(str);
iss >> t;
}
};
};
Now we can generate required type by passing these definitions to xany
typedef xany<boost::mpl::list<to_string_method<boost::mpl::_1>, from_string_method<boost::mpl::_1> > > string_convertable_any;
After instansietion boost::mpl::_1 will be replaced by xany.
string_convertable_any provides to_string and from_string additional members.
The string_convertable_any will accept any type that satisfies ValueType requirements of boost::any and for which stream insertion and extraction operations are defined.
string_convertable_any a(10);
std::string str = a.to_string();
a.from_string("100");
Let's generate simple generalized function adaptor using xany.
For simplicity our any_function will support up to two arguments.
template <typename FunctionSignature, typename Xany>
struct call_method;
template <typename R, typename Xany>
struct call_method<R (), Xany>
{
typedef R (Xany::* signature) ();
template <typename T>
struct wrapper
: public T
{
R operator() ()
{
return this->call(call_method());
}
};
struct implementation
{
template <typename T>
R operator() (T& t) const
{
return t();
}
};
};
template <typename R, typename T1, typename Xany>
struct call_method<R (T1), Xany>
{
typedef R (Xany::* signature) (T1);
template <typename T>
struct wrapper
: public T
{
R operator() (T1 a1)
{
return this->call(call_method(), a1);
}
};
struct implementation
{
template <typename T>
R operator() (T& t, T1 a1) const
{
return t(a1);
}
};
};
template <typename R, typename T1, typename T2, typename Xany>
struct call_method<R (T1, T2), Xany>
{
typedef R (Xany::* signature) (T1, T2);
template <typename T>
struct wrapper
: public T
{
R operator() (T1 a1, T2 a2)
{
return this->call(call_method(), a1, a2);
}
};
struct implementation
{
template <typename T>
R operator() (T& t, T1 a1, T2 a2) const
{
return t(a1, a2);
}
};
};
We can define any_function as Boost MPLs Higher-Order Metafunction.
struct any_function_f
{
template <typename Signature>
struct apply
{
typedef xany<boost::mpl::list<call_method<Signature, boost::mpl::_1> > > type;
};
};
boost::mpl::apply<any_function_f, Signature> will be generalized function adaptor for Signature.
Let's generate generalized adaptor for equality comparable types
template <typename Xany>
struct equal_method
{
typedef bool (Xany::* signature) (const Xany&) const;
template <typename T>
struct wrapper
: public T
{
bool operator== (const Xany& other) const
{
return this->call(equal_method(), other);
}
};
struct implementation
{
template <typename T>
bool operator() (const T& t, const Xany& other) const
{
return t == xany_cast<T>(other);
}
};
};
template <typename Xany>
struct nequal_method
{
typedef bool (Xany::* signature) (const Xany&) const;
template <typename T>
struct wrapper
: public T
{
bool operator!= (const Xany& other) const
{
return this->call(nequal_method(), other);
}
};
struct implementation
{
template <typename T>
bool operator() (const T& t, const Xany& other) const
{
return t != xany_cast<T>(other);
}
};
};
typedef xany<boost::mpl::list<equal_method<boost::mpl::_1>, nequal_method<boost::mpl::_1> > > comparable_any;
comparable_any a1(10);
comparable_any a2(12);
comparable_any a3(10);
assert(! (a1 == a2) );
assert(a1 == a3);
assert(a1 != a2);