太晚了,我知道,但是这个呢:
// MSVC++ 2010 SP1 x86
// boost 1.53
#include <tuple>
#include <memory>
// test
#include <iostream>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/pair.hpp>
#include <boost/mpl/begin.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/unpack_args.hpp>
#include <boost/mpl/apply.hpp>
// test
#include <boost/range/algorithm/for_each.hpp>
/*! \internal
*/
namespace detail
{
/*! \internal
*/
namespace runtime_template
{
/*! \internal
fwd
*/
template <
typename Template
, typename Types
, typename Map // top level map iterator
, typename LastMap // top level map iterator
, int Index
, bool Done = std::is_same<Map, LastMap>::value
>
struct apply_recursive_t;
/*! \internal
fwd
*/
template <
typename Template
, typename Types
, typename Map // top level map iterator
, typename LastMap // top level map iterator
, typename First
, typename Last
, int Index
, bool Enable = !std::is_same<First, Last>::value
>
struct apply_mapping_recursive_t;
/*! \internal
run time compare key values + compile time push_back on \a Types
*/
template <
typename Template
, typename Types
, typename Map // top level map iterator
, typename LastMap // top level map iterator
, typename First
, typename Last
, int Index // current argument
, bool Enable /* = !std::is_same<First, Last>::value */
>
struct apply_mapping_recursive_t
{
typedef void result_type;
template <typename TypeIds, typename T>
inline static void apply(const TypeIds& typeIds, T&& t)
{ namespace mpl = boost::mpl;
typedef typename mpl::deref<First>::type key_value_pair;
typedef typename mpl::first<key_value_pair>::type typeId; // mpl::int
if (typeId::value == std::get<Index>(typeIds))
{
apply_recursive_t<
Template
, typename mpl::push_back<
Types
, typename mpl::second<key_value_pair>::type
>::type
, typename mpl::next<Map>::type
, LastMap
, Index + 1
>::apply(typeIds, std::forward<T>(t));
}
else
{
apply_mapping_recursive_t<
Template
, Types
, Map
, LastMap
, typename mpl::next<First>::type
, Last
, Index
>::apply(typeIds, std::forward<T>(t));
}
}
};
/*! \internal
mapping not found
\note should never be invoked, but must compile
*/
template <
typename Template
, typename Types
, typename Map // top level map iterator
, typename LastMap // top level map iterator
, typename First
, typename Last
, int Index
>
struct apply_mapping_recursive_t<
Template
, Types
, Map
, LastMap
, First
, Last
, Index
, false
>
{
typedef void result_type;
template <typename TypeIds, typename T>
inline static void apply(const TypeIds& /* typeIds */, T&& /* t */)
{
BOOST_ASSERT(false);
}
};
/*! \internal
push_back on \a Types template types recursively
*/
template <
typename Template
, typename Types
, typename Map // top level map iterator
, typename LastMap // top level map iterator
, int Index
, bool Done /* = std::is_same<Map, LastMap>::value */
>
struct apply_recursive_t
{
typedef void result_type;
template <typename TypeIds, typename T>
inline static void apply(const TypeIds& typeIds, T&& t)
{ namespace mpl = boost::mpl;
typedef typename mpl::deref<Map>::type Mapping; // [key;type] pair vector
apply_mapping_recursive_t<
Template
, Types
, Map
, LastMap
, typename mpl::begin<Mapping>::type
, typename mpl::end<Mapping>::type
, Index
>::apply(typeIds, std::forward<T>(t));
}
};
/*! \internal
done! replace mpl placeholders of \a Template with the now complete \a Types
and invoke result
*/
template <
typename Template
, typename Types
, typename Map
, typename LastMap
, int Index
>
struct apply_recursive_t<
Template
, Types
, Map
, LastMap
, Index
, true
>
{
typedef void result_type;
template <typename TypeIds, typename T>
inline static void apply(const TypeIds& /* typeIds */, T&& t)
{ namespace mpl = boost::mpl;
typename mpl::apply<
mpl::unpack_args<Template>
, Types
>::type()(std::forward<T>(t));
}
};
/*! \internal
helper functor to be used with invoke_runtime_template()
\note cool: mpl::apply works with nested placeholders types!
*/
template <typename Template>
struct make_runtime_template_t
{
typedef void result_type;
template <typename Base>
inline void operator()(std::unique_ptr<Base>* base) const
{
base->reset(new Template());
}
};
} // namespace runtime_template
} // namespace detail
/*! \brief runtime template parameter selection
\param Template functor<_, ...> placeholder expression
\param Maps mpl::vector<mpl::vector<mpl::pair<int, type>, ...>, ...>
\param Types std::tuple<int, ...> type ids
\param T functor argument type
\note all permutations must be compilable (they will be compiled of course)
\note compile time: O(n!) run time: O(n)
\sa invoke_runtime_template()
\author slow
*/
template <
typename Template
, typename Map
, typename Types
, typename T
>
inline void invoke_runtime_template(const Types& types, T&& t)
{ namespace mpl = boost::mpl;
BOOST_STATIC_ASSERT(mpl::size<Map>::value == std::tuple_size<Types>::value);
detail::runtime_template::apply_recursive_t<
Template
, mpl::vector<>
, typename mpl::begin<Map>::type
, typename mpl::end<Map>::type
, 0
>::apply(types, std::forward<T>(t));
}
/*! \sa invoke_runtime_template()
*/
template <
typename Template
, typename Map
, typename Base
, typename Types
>
inline void make_runtime_template(const Types& types, std::unique_ptr<Base>* base)
{
invoke_runtime_template<
detail::runtime_template::make_runtime_template_t<Template>
, Map
>(types, base);
}
/*! \overload
*/
template <
typename Base
, typename Template
, typename Map
, typename Types
>
inline std::unique_ptr<Base> make_runtime_template(const Types& types)
{
std::unique_ptr<Base> result;
make_runtime_template<Template, Map>(types, &result);
return result;
}
////////////////////////////////////////////////////////////////////////////////
namespace mpl = boost::mpl;
using mpl::_;
class MyClassInterface {
public:
virtual ~MyClassInterface() {}
virtual double foo(double) = 0;
};
template <int P1, int P2, int P3>
class MyClass
: public MyClassInterface {
public:
double foo(double /*a*/) {
// complex computation dependent on P1, P2, P3
std::wcout << typeid(MyClass<P1, P2, P3>).name() << std::endl;
return 42.0;
}
// more methods and fields (dependent on P1, P2, P3)
};
// wrapper for transforming types (mpl::int) to values
template <typename P1, typename P2, typename P3>
struct MyFactory
{
inline void operator()(std::unique_ptr<MyClassInterface>* result) const
{
result->reset(new MyClass<P1::value, P2::value, P3::value>());
}
};
template <int I>
struct MyConstant
: boost::mpl::pair<
boost::mpl::int_<I>
, boost::mpl::int_<I>
> {};
std::unique_ptr<MyClassInterface> Factor(const std::tuple<int, int, int>& constants) {
typedef mpl::vector<
MyConstant<0>
, MyConstant<1>
, MyConstant<2>
, MyConstant<3>
// ...
> MyRange;
std::unique_ptr<MyClassInterface> result;
invoke_runtime_template<
MyFactory<_, _, _>
, mpl::vector<MyRange, MyRange, MyRange>
>(constants, &result);
return result;
}
int main(int /*argc*/, char* /*argv*/[])
{
typedef std::tuple<int, int, int> Tuple;
const Tuple Permutations[] =
{
std::make_tuple(0, 0, 0)
, std::make_tuple(0, 0, 1)
, std::make_tuple(0, 1, 0)
, std::make_tuple(0, 1, 1)
, std::make_tuple(1, 0, 0)
, std::make_tuple(1, 2, 3)
, std::make_tuple(1, 1, 0)
, std::make_tuple(1, 1, 1)
// ...
};
boost::for_each(Permutations, [](const Tuple& constants) { Factor(constants)->foo(42.0); });
return 0;
}