.
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);