Last active
August 29, 2015 14:25
-
-
Save Sleepingwell/e7521d8d88a417bff143 to your computer and use it in GitHub Desktop.
Create a sequence of types (std::pair in this dummy example) containing the outer product of two input sequences of types.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* A 'functor descriptor' that can be used to generate a runtime polymorphic functor | |
* for a set of input/ouput types. To be used to create python extensions in C++ for | |
* wrapping with boost::python, such that the functors can be configured in Python | |
* then applied to a number (greater than 1) of non-polymorphic input/output types | |
* in C++ (the types used in practice will not be those in first_types and second | |
* types, which are just for convenience). | |
*/ | |
#include <new> // placement new | |
#include <typeinfo> // typeid | |
#include <cstdio> // printf | |
#include <stdexcept> // runtime_error | |
#include <boost/mpl/vector.hpp> | |
#include <boost/mpl/transform.hpp> | |
#include <boost/mpl/accumulate.hpp> | |
#include <boost/mpl/insert_range.hpp> | |
#include <boost/mpl/end.hpp> | |
#include <boost/mpl/inherit_linearly.hpp> | |
#include <boost/mpl/inherit.hpp> | |
#include <boost/mpl/empty_base.hpp> | |
#include <boost/fusion/sequence.hpp> // at_c | |
#include <boost/fusion/container/vector.hpp> | |
// while I think the following is valid syntax, it does not work on msvc 2012 | |
//template< | |
// typename T0 = boost::fusion::void_, | |
// typename T1 = boost::fusion::void_, | |
// typename T2 = boost::fusion::void_, | |
// typename T3 = boost::fusion::void_, | |
// typename T4 = boost::fusion::void_, | |
// typename T5 = boost::fusion::void_, | |
// typename T6 = boost::fusion::void_, | |
// typename T7 = boost::fusion::void_, | |
// typename T8 = boost::fusion::void_, | |
// typename T9 = boost::fusion::void_ | |
//> using args_ = boost::fusion::vector<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>; | |
// ... so do this instead | |
#define args_ boost::fusion::vector | |
/** | |
* @brief Virtual base class for all functors. | |
*/ | |
template<typename InPoint, typename OutPoint> | |
struct PymeseriesFunctorBase { | |
virtual ~PymeseriesFunctorBase(void) {} | |
virtual double operator()(InPoint const& inPoint, OutPoint& outPoint, double weight) { | |
throw std::runtime_error("Operation not supported"); | |
} | |
virtual void finaliseTimeSeries(OutPoint& outPoint) { }; | |
}; | |
namespace detail { | |
// tools for building the base class of all functor descriptors | |
template< | |
template<typename, typename> class FuncToWrap | |
> | |
struct double_bind_base { | |
template<typename First> | |
struct apply { | |
struct type { | |
template<typename Second> | |
struct apply { | |
typedef FuncToWrap<First, Second> type; | |
}; | |
}; | |
}; | |
}; | |
template<typename Seq> | |
struct second_transform_base { | |
template<typename State, typename Arg2> | |
struct apply { | |
struct apply_arg { | |
template<typename F> | |
struct apply { | |
typedef typename F::template apply<Arg2>::type type; | |
}; | |
}; | |
typedef typename boost::mpl::insert_range< | |
State, | |
typename boost::mpl::end<State>::type, | |
typename boost::mpl::transform<Seq, apply_arg>::type | |
>::type type; | |
}; | |
}; | |
// base class for functor descriptors | |
template<typename InPoint, typename OutPoint> | |
struct functor_descriptor_base { | |
typedef PymeseriesFunctorBase<InPoint, OutPoint> abstract_functor_type; | |
virtual ~functor_descriptor_base(void) {}; | |
virtual abstract_functor_type* makeFunctor(InPoint const&, OutPoint const&) const = 0; | |
}; | |
template<typename FirstTypes, typename SecondTypes> | |
struct make_pymeseries_functor_abstract_base { | |
// wrap the abstruct functor up | |
typedef typename boost::mpl::transform<FirstTypes, double_bind_base<functor_descriptor_base> >::type abstract_firsts; | |
typedef typename boost::mpl::accumulate<SecondTypes, boost::mpl::vector0<>, second_transform_base<abstract_firsts> >::type funtor_base_classes; | |
// make the class with base classes | |
typedef typename boost::mpl::inherit_linearly< | |
funtor_base_classes, | |
boost::mpl::inherit<boost::mpl::_1, boost::mpl::_2> | |
>::type virtual_base_type; | |
struct type : virtual_base_type { | |
typedef FirstTypes first_types; | |
typedef SecondTypes second_types; | |
}; | |
}; | |
} // end namespace detail | |
// list of classes to specialise functors for | |
typedef boost::mpl::vector2<float, double> first_types; | |
typedef boost::mpl::vector2<int, long> second_types; | |
typedef detail::make_pymeseries_functor_abstract_base<first_types, second_types>::type pymeseries_functor_base; | |
namespace detail { | |
// tools for building concrete functors. | |
template< | |
typename Derived, | |
template<typename, typename> class FuncToWrap, | |
template<template<typename, typename> class, typename, typename, typename, typename> class FuncWrapper | |
> | |
struct triple_bind_derived { | |
template<typename First> | |
struct apply { | |
struct type { | |
template<typename Second> | |
struct apply { | |
struct type { | |
template<typename Base> | |
struct apply { | |
typedef FuncWrapper<FuncToWrap, First, Second, Derived, Base> type; | |
}; | |
}; | |
}; | |
}; | |
}; | |
}; | |
template<typename Seq> | |
struct second_transform_derived { | |
template<typename State, typename Arg2> | |
struct apply { | |
// metafunction class add the second type (second apply in triple_bind_derived). | |
struct apply_arg { | |
template<typename F> | |
struct apply { | |
typedef typename F::template apply<Arg2>::type type; | |
}; | |
}; | |
// contains the first and second points | |
typedef typename boost::mpl::transform<Seq, apply_arg>::type ready_for_base; | |
// metafunction class to add the base class (third apply in triple_bind_derived). | |
struct extend { | |
template<typename Base, typename Derived> | |
struct apply { | |
typedef typename Derived::template apply<Base>::type type; | |
}; | |
}; | |
// now inherit recursively | |
typedef typename boost::mpl::accumulate< | |
ready_for_base, | |
State, | |
extend | |
>::type type; | |
}; | |
}; | |
// class for wrapping functors. | |
template< | |
template<typename, typename> class WrappedFunctor, | |
typename InPoint, | |
typename OutPoint, | |
typename Derived, | |
typename BaseClass | |
> | |
struct functor_wrapper : BaseClass { | |
virtual WrappedFunctor<InPoint, OutPoint>* makeFunctor(InPoint const&, OutPoint const&) const { | |
return static_cast<Derived const*>(this)->template makeFunctor<InPoint, OutPoint>(); | |
} | |
}; | |
template< | |
typename Derived, | |
template<typename, typename> class HeldFunctor, | |
typename first_types, | |
typename second_types | |
> | |
struct make_pymeseries_functor_concrete_base { | |
typedef typename boost::mpl::transform<first_types, detail::triple_bind_derived<Derived, HeldFunctor, detail::functor_wrapper> >::type first_bounds; | |
typedef typename boost::mpl::accumulate<second_types, pymeseries_functor_base, detail::second_transform_derived<first_bounds> >::type type; | |
}; | |
template< | |
typename first_types, | |
typename second_types, | |
template<typename, typename> class HeldFunctor, | |
typename Args = boost::fusion::vector<> | |
> | |
struct Functor : make_pymeseries_functor_concrete_base< | |
Functor<first_types, second_types, HeldFunctor, Args>, | |
HeldFunctor, | |
first_types, | |
second_types | |
>::type { | |
Functor(void) { } | |
template<typename InPoint, typename OutPoint> | |
HeldFunctor<InPoint, OutPoint>* makeFunctor(void) const { | |
return new HeldFunctor<InPoint, OutPoint>(); | |
} | |
}; | |
template< | |
typename first_types, | |
typename second_types, | |
template<typename, typename> class HeldFunctor, | |
typename T1 | |
> | |
struct Functor<first_types, second_types, HeldFunctor, args_<T1> > : make_pymeseries_functor_concrete_base< | |
Functor<first_types, second_types, HeldFunctor, args_<T1> >, | |
HeldFunctor, | |
first_types, | |
second_types | |
>::type { | |
typedef args_<T1> arg_pack_type; | |
Functor( | |
T1 const& t1 | |
) : argPack_(t1) { } | |
template<typename InPoint, typename OutPoint> | |
HeldFunctor<InPoint, OutPoint>* makeFunctor(void) const { | |
return new HeldFunctor<InPoint, OutPoint>( | |
boost::fusion::at_c<0>(argPack_) | |
); | |
} | |
private: | |
arg_pack_type | |
argPack_; | |
}; | |
template< | |
typename first_types, | |
typename second_types, | |
template<typename, typename> class HeldFunctor, | |
typename T1, | |
typename T2 | |
> | |
struct Functor<first_types, second_types, HeldFunctor, args_<T1, T2> > : make_pymeseries_functor_concrete_base< | |
Functor<first_types, second_types, HeldFunctor, args_<T1, T2> >, | |
HeldFunctor, | |
first_types, | |
second_types | |
>::type { | |
typedef args_<T1, T2> arg_pack_type; | |
Functor( | |
T1 const& t1, | |
T2 const& t2 | |
) : argPack_(t1, t2) { } | |
template<typename InPoint, typename OutPoint> | |
HeldFunctor<InPoint, OutPoint>* makeFunctor(void) const { | |
return new HeldFunctor<InPoint, OutPoint>( | |
boost::fusion::at_c<0>(argPack_), | |
boost::fusion::at_c<1>(argPack_) | |
); | |
} | |
private: | |
arg_pack_type | |
argPack_; | |
}; | |
template< | |
typename first_types, | |
typename second_types, | |
template<typename, typename> class HeldFunctor, | |
typename T1, | |
typename T2, | |
typename T3 | |
> | |
struct Functor<first_types, second_types, HeldFunctor, args_<T1, T2, T3> > : make_pymeseries_functor_concrete_base< | |
Functor<first_types, second_types, HeldFunctor, args_<T1, T2, T3> >, | |
HeldFunctor, | |
first_types, | |
second_types | |
>::type { | |
typedef args_<T1, T2, T3> arg_pack_type; | |
Functor( | |
T1 const& t1, | |
T2 const& t2, | |
T3 const& t3 | |
) : argPack_(t1, t2, t3) { } | |
template<typename InPoint, typename OutPoint> | |
HeldFunctor<InPoint, OutPoint>* makeFunctor(void) const { | |
return new HeldFunctor<InPoint, OutPoint>( | |
boost::fusion::at_c<0>(argPack_), | |
boost::fusion::at_c<1>(argPack_), | |
boost::fusion::at_c<2>(argPack_) | |
); | |
} | |
private: | |
arg_pack_type | |
argPack_; | |
}; | |
template< | |
typename first_types, | |
typename second_types, | |
template<typename, typename> class HeldFunctor, | |
typename T1, | |
typename T2, | |
typename T3, | |
typename T4 | |
> | |
struct Functor<first_types, second_types, HeldFunctor, args_<T1, T2, T3, T4> > : make_pymeseries_functor_concrete_base< | |
Functor<first_types, second_types, HeldFunctor, args_<T1, T2, T3, T4> >, | |
HeldFunctor, | |
first_types, | |
second_types | |
>::type { | |
typedef args_<T1, T2, T3, T4> arg_pack_type; | |
Functor( | |
T1 const& t1, | |
T2 const& t2, | |
T3 const& t3, | |
T4 const& t4 | |
) : argPack_(t1, t2, t3, t4) { } | |
template<typename InPoint, typename OutPoint> | |
HeldFunctor<InPoint, OutPoint>* makeFunctor(void) const { | |
return new HeldFunctor<InPoint, OutPoint>( | |
boost::fusion::at_c<0>(argPack_), | |
boost::fusion::at_c<1>(argPack_), | |
boost::fusion::at_c<2>(argPack_), | |
boost::fusion::at_c<3>(argPack_) | |
); | |
} | |
private: | |
arg_pack_type | |
argPack_; | |
}; | |
template< | |
typename first_types, | |
typename second_types, | |
template<typename, typename> class HeldFunctor, | |
typename T1, | |
typename T2, | |
typename T3, | |
typename T4, | |
typename T5 | |
> | |
struct Functor<first_types, second_types, HeldFunctor, args_<T1, T2, T3, T4, T5> > : make_pymeseries_functor_concrete_base< | |
Functor<first_types, second_types, HeldFunctor, args_<T1, T2, T3, T4, T5> >, | |
HeldFunctor, | |
first_types, | |
second_types | |
>::type { | |
typedef args_<T1, T2, T3, T4, T5> arg_pack_type; | |
Functor( | |
T1 const& t1, | |
T2 const& t2, | |
T3 const& t3, | |
T4 const& t4, | |
T5 const& t5 | |
) : argPack_(t1, t2, t3, t4, t5) { } | |
template<typename InPoint, typename OutPoint> | |
HeldFunctor<InPoint, OutPoint>* makeFunctor(void) const { | |
return new HeldFunctor<InPoint, OutPoint>( | |
boost::fusion::at_c<0>(argPack_), | |
boost::fusion::at_c<1>(argPack_), | |
boost::fusion::at_c<2>(argPack_), | |
boost::fusion::at_c<3>(argPack_), | |
boost::fusion::at_c<4>(argPack_) | |
); | |
} | |
private: | |
arg_pack_type | |
argPack_; | |
}; | |
template< | |
typename first_types, | |
typename second_types, | |
template<typename, typename> class HeldFunctor, | |
typename T1, | |
typename T2, | |
typename T3, | |
typename T4, | |
typename T5, | |
typename T6 | |
> | |
struct Functor<first_types, second_types, HeldFunctor, args_<T1, T2, T3, T4, T5, T6> > : make_pymeseries_functor_concrete_base< | |
Functor<first_types, second_types, HeldFunctor, args_<T1, T2, T3, T4, T5, T6> >, | |
HeldFunctor, | |
first_types, | |
second_types | |
>::type { | |
typedef args_<T1, T2, T3, T4, T5, T6> arg_pack_type; | |
Functor( | |
T1 const& t1, | |
T2 const& t2, | |
T3 const& t3, | |
T4 const& t4, | |
T5 const& t5, | |
T6 const& t6 | |
) : argPack_(t1, t2, t3, t4, t5, t6) { } | |
template<typename InPoint, typename OutPoint> | |
HeldFunctor<InPoint, OutPoint>* makeFunctor(void) const { | |
return new HeldFunctor<InPoint, OutPoint>( | |
boost::fusion::at_c<0>(argPack_), | |
boost::fusion::at_c<1>(argPack_), | |
boost::fusion::at_c<2>(argPack_), | |
boost::fusion::at_c<3>(argPack_), | |
boost::fusion::at_c<4>(argPack_), | |
boost::fusion::at_c<5>(argPack_) | |
); | |
} | |
private: | |
arg_pack_type | |
argPack_; | |
}; | |
template< | |
typename first_types, | |
typename second_types, | |
template<typename, typename> class HeldFunctor, | |
typename T1, | |
typename T2, | |
typename T3, | |
typename T4, | |
typename T5, | |
typename T6, | |
typename T7 | |
> | |
struct Functor<first_types, second_types, HeldFunctor, args_<T1, T2, T3, T4, T5, T6, T7> > : make_pymeseries_functor_concrete_base< | |
Functor<first_types, second_types, HeldFunctor, args_<T1, T2, T3, T4, T5, T6, T7> >, | |
HeldFunctor, | |
first_types, | |
second_types | |
>::type { | |
typedef args_<T1, T2, T3, T4, T5, T6, T7> arg_pack_type; | |
Functor( | |
T1 const& t1, | |
T2 const& t2, | |
T3 const& t3, | |
T4 const& t4, | |
T5 const& t5, | |
T6 const& t6, | |
T7 const& t7 | |
) : argPack_(t1, t2, t3, t4, t5, t6, t7) { } | |
template<typename InPoint, typename OutPoint> | |
HeldFunctor<InPoint, OutPoint>* makeFunctor(void) const { | |
return new HeldFunctor<InPoint, OutPoint>( | |
boost::fusion::at_c<0>(argPack_), | |
boost::fusion::at_c<1>(argPack_), | |
boost::fusion::at_c<2>(argPack_), | |
boost::fusion::at_c<3>(argPack_), | |
boost::fusion::at_c<4>(argPack_), | |
boost::fusion::at_c<5>(argPack_), | |
boost::fusion::at_c<6>(argPack_) | |
); | |
} | |
private: | |
arg_pack_type | |
argPack_; | |
}; | |
template< | |
typename first_types, | |
typename second_types, | |
template<typename, typename> class HeldFunctor, | |
typename T1, | |
typename T2, | |
typename T3, | |
typename T4, | |
typename T5, | |
typename T6, | |
typename T7, | |
typename T8 | |
> | |
struct Functor<first_types, second_types, HeldFunctor, args_<T1, T2, T3, T4, T5, T6, T7, T8> > : make_pymeseries_functor_concrete_base< | |
Functor<first_types, second_types, HeldFunctor, args_<T1, T2, T3, T4, T5, T6, T7, T8> >, | |
HeldFunctor, | |
first_types, | |
second_types | |
>::type { | |
typedef args_<T1, T2, T3, T4, T5, T6, T7, T8> arg_pack_type; | |
Functor( | |
T1 const& t1, | |
T2 const& t2, | |
T3 const& t3, | |
T4 const& t4, | |
T5 const& t5, | |
T6 const& t6, | |
T7 const& t7, | |
T8 const& t8 | |
) : argPack_(t1, t2, t3, t4, t5, t6, t7, t8) { } | |
template<typename InPoint, typename OutPoint> | |
HeldFunctor<InPoint, OutPoint>* makeFunctor(void) const { | |
return new HeldFunctor<InPoint, OutPoint>( | |
boost::fusion::at_c<0>(argPack_), | |
boost::fusion::at_c<1>(argPack_), | |
boost::fusion::at_c<2>(argPack_), | |
boost::fusion::at_c<3>(argPack_), | |
boost::fusion::at_c<4>(argPack_), | |
boost::fusion::at_c<5>(argPack_), | |
boost::fusion::at_c<6>(argPack_), | |
boost::fusion::at_c<7>(argPack_) | |
); | |
} | |
private: | |
arg_pack_type | |
argPack_; | |
}; | |
template< | |
typename first_types, | |
typename second_types, | |
template<typename, typename> class HeldFunctor, | |
typename T1, | |
typename T2, | |
typename T3, | |
typename T4, | |
typename T5, | |
typename T6, | |
typename T7, | |
typename T8, | |
typename T9 | |
> | |
struct Functor<first_types, second_types, HeldFunctor, args_<T1, T2, T3, T4, T5, T6, T7, T8, T9> > : make_pymeseries_functor_concrete_base< | |
Functor<first_types, second_types, HeldFunctor, args_<T1, T2, T3, T4, T5, T6, T7, T8, T9> >, | |
HeldFunctor, | |
first_types, | |
second_types | |
>::type { | |
typedef args_<T1, T2, T3, T4, T5, T6, T7, T8, T9> arg_pack_type; | |
Functor( | |
T1 const& t1, | |
T2 const& t2, | |
T3 const& t3, | |
T4 const& t4, | |
T5 const& t5, | |
T6 const& t6, | |
T7 const& t7, | |
T8 const& t8, | |
T9 const& t9 | |
) : argPack_(t1, t2, t3, t4, t5, t6, t7, t8, t9) { } | |
template<typename InPoint, typename OutPoint> | |
HeldFunctor<InPoint, OutPoint>* makeFunctor(void) const { | |
return new HeldFunctor<InPoint, OutPoint>( | |
boost::fusion::at_c<0>(argPack_), | |
boost::fusion::at_c<1>(argPack_), | |
boost::fusion::at_c<2>(argPack_), | |
boost::fusion::at_c<3>(argPack_), | |
boost::fusion::at_c<4>(argPack_), | |
boost::fusion::at_c<5>(argPack_), | |
boost::fusion::at_c<6>(argPack_), | |
boost::fusion::at_c<7>(argPack_), | |
boost::fusion::at_c<8>(argPack_) | |
); | |
} | |
private: | |
arg_pack_type | |
argPack_; | |
}; | |
template< | |
typename first_types, | |
typename second_types, | |
template<typename, typename> class HeldFunctor, | |
typename T1, | |
typename T2, | |
typename T3, | |
typename T4, | |
typename T5, | |
typename T6, | |
typename T7, | |
typename T8, | |
typename T9, | |
typename T10 | |
> | |
struct Functor<first_types, second_types, HeldFunctor, args_<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> > : make_pymeseries_functor_concrete_base< | |
Functor<first_types, second_types, HeldFunctor, args_<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> >, | |
HeldFunctor, | |
first_types, | |
second_types | |
>::type { | |
typedef args_<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> arg_pack_type; | |
Functor( | |
T1 const& t1, | |
T2 const& t2, | |
T3 const& t3, | |
T4 const& t4, | |
T5 const& t5, | |
T6 const& t6, | |
T7 const& t7, | |
T8 const& t8, | |
T9 const& t9, | |
T10 const& t10 | |
) : argPack_(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) { } | |
template<typename InPoint, typename OutPoint> | |
HeldFunctor<InPoint, OutPoint>* makeFunctor(void) const { | |
return new HeldFunctor<InPoint, OutPoint>( | |
boost::fusion::at_c<0>(argPack_), | |
boost::fusion::at_c<1>(argPack_), | |
boost::fusion::at_c<2>(argPack_), | |
boost::fusion::at_c<3>(argPack_), | |
boost::fusion::at_c<4>(argPack_), | |
boost::fusion::at_c<5>(argPack_), | |
boost::fusion::at_c<6>(argPack_), | |
boost::fusion::at_c<7>(argPack_), | |
boost::fusion::at_c<8>(argPack_), | |
boost::fusion::at_c<9>(argPack_) | |
); | |
} | |
private: | |
arg_pack_type | |
argPack_; | |
}; | |
} // end namespace detail | |
// metafunction to wrap up a functor | |
template<template<typename, typename> class FunctorToWrap, typename ConstructorArgs = boost::mpl::na> | |
struct make_pymeseries_functor { | |
typedef typename pymeseries_functor_base::first_types first_types; | |
typedef typename pymeseries_functor_base::second_types second_types; | |
typedef detail::Functor<first_types, second_types, FunctorToWrap, ConstructorArgs> type; | |
}; | |
// A test functor with 0 arg constructor | |
template<typename InPoint, typename OutPoint> | |
struct TestFunctor0 : PymeseriesFunctorBase<InPoint, OutPoint> { | |
double operator()(InPoint const& inPoint, OutPoint const& outPoint) { | |
printf("%s -> %s\n", typeid(InPoint).name(), typeid(OutPoint).name()); | |
return inPoint + outPoint; | |
} | |
}; | |
// wrap the test functor up into a descriptor. | |
typedef make_pymeseries_functor<TestFunctor0>::type test_functor_descriptor0; | |
// A test functor with 1 arg constructor | |
template<typename InPoint, typename OutPoint> | |
struct TestFunctor1 : PymeseriesFunctorBase<InPoint, OutPoint> { | |
TestFunctor1(double val) : val_(val) {} | |
double operator()(InPoint const& inPoint, OutPoint& outPoint, double weight) { | |
printf("%s -> %s with %f\n", typeid(InPoint).name(), typeid(OutPoint).name(), val_); | |
return inPoint + outPoint; | |
} | |
double val_; | |
}; | |
// wrap the test functor up into a descriptor. | |
typedef make_pymeseries_functor<TestFunctor1, args_<double> >::type test_functor_descriptor1; | |
// function to excercise it | |
template<typename FirstType, typename SecondType> | |
int test(pymeseries_functor_base const& functorBase) { | |
typedef detail::functor_descriptor_base<FirstType, SecondType> FuncDesc; | |
typedef typename FuncDesc::abstract_functor_type abstract_functor_type; | |
abstract_functor_type* functor(NULL); | |
int res(0); | |
SecondType st(21); | |
try { | |
functor = static_cast<FuncDesc const&>(functorBase).makeFunctor(FirstType(), SecondType()); | |
printf("and the answer is... %f\n", (*functor)(21, st, 1.0)); | |
} catch(...) { | |
printf("whoops\n"); | |
res = 1; | |
} | |
if(functor) { | |
delete functor; | |
} | |
return res; | |
} | |
int main(int argc, char* argv[]) { | |
test_functor_descriptor0 bc0; | |
test<float, long>(bc0); | |
test_functor_descriptor1 bc1(1.0); | |
test<double, int>(bc1); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment