Reputation: 1493
I'm exploring the boost library code and found the following strange struct definition.
struct add_ints_only
{
template<typename T>
struct result;
template <typename State, typename T>
struct result<add_ints_only(State, T)> // what's going on here?
{
typedef typename boost::remove_const<
typename boost::remove_reference<State>::type>::type type;
};
template <typename State, typename T>
State
operator()(State const& state, T const& /*x*/) const
{
return state;
}
int
operator()(int state, int x) const
{
return x + state;
}
};
What is it for?
Upvotes: 3
Views: 403
Reputation: 9199
I guess you are looking to some Boost.Fusion stuff or something similar.
In particular add_ints_only is model of Polymorphic Function Object concept.
Polymorphic Function Object provides polymorphic operator(), which may be overloaded or may be a template. Result type of operator() may differ based on it's parameter types.
It is similar in something to Adaptable Unary Function concept from STL, which should provide nested ::result_type.
But result type of Polymorphic Function Object may differ depending on arguments types passed to operator(). So, some more powerfull facility than single ::result_type should be used to get result type based on types of arguments of operator().
template <typename State, typename T>
struct result<add_ints_only(State, T)> // ...
This syntax is partial specialization of class.
add_ints_only(State, T)
Is type of function which returns add_ints_only and takes Stage and T as a parameter.
Itself, this type is not not meaningfull - you are not going to return add_ints_only. It is just convenient form of type argument passing - it looks like call of add_ints_only function. And it allow to have specialization for different numbers of arguments.
Here how it works:
#include <boost/utility/result_of.hpp>
#include <typeinfo>
#include <iostream>
#include <ostream>
using namespace std;
struct PolymorphicFunctionObject
{
template<typename T> struct result;
template<typename Arg>
struct result< PolymorphicFunctionObject(Arg) >
{
typedef Arg type;
};
template<typename Arg1,typename Arg2>
struct result< PolymorphicFunctionObject(Arg1,Arg2) >
{
typedef Arg2 type;
};
template<typename Arg>
Arg operator()(Arg t) const
{
return t;
}
template<typename Arg1,typename Arg2>
Arg2 operator()(Arg1 t1,Arg2 t2) const
{
return t2;
}
};
int main()
{
cout << typeid
(
PolymorphicFunctionObject::result< PolymorphicFunctionObject(int) >::type
).name() << endl;
// Output is - int
cout << typeid
(
PolymorphicFunctionObject::result< PolymorphicFunctionObject(char,double) >::type
).name() << endl;
// Output is - double
// -----------------
// Or using boost::result_of, which queries ::result internally:
cout << typeid
(
boost::result_of< PolymorphicFunctionObject(short) >::type
).name() << endl;
// Output is - short
cout << typeid
(
boost::result_of< PolymorphicFunctionObject(char,float) >::type
).name() << endl;
// Output is - float
// ------------------
// Or using C++11 decltype:
cout << typeid
(
decltype( PolymorphicFunctionObject()( long() ) )
).name() << endl;
// Output is - long
cout << typeid
(
decltype( PolymorphicFunctionObject()( long(),unsigned() ) )
).name() << endl;
// Output is - unsigned int
}
As you can see, result type querying syntax:
boost::result_of< PolymorphicFunctionObject(short) >::type
boost::result_of< PolymorphicFunctionObject(char,float) >::type
Looks similar to normal function call.
P.S. In C++11 this stuff is not need, due to presence of decltype, which can be used to get type of result automatically. For instance:
decltype( PolymorphicFunctionObject()( long(),unsigned() ) )
Upvotes: 3
Reputation: 157334
result
is partially specialized on the function type add_ints_only(State, T)
.
The purpose is that code that wants to know the type that the functor add_ints_only
returns with particular argument types can inquire by writing:
typedef typename add_ints_only::result<add_ints_only(arg1_type, arg2_type)>::type
result_type;
e.g.
template<typename U, typename V> void foo(U u, V v) {
typename add_ints_only::result<add_ints_only(arg1_type, arg2_type)>::type
result = add_ints_only()(u, v);
}
This is useful for functors that can return different types depending on their operator()
argument types.
Upvotes: 3