我正在尝试概括先前在SO here上提供的解决方案,该解决方案使用boost MPL来实例化函数的许多模板,并在运行时选择正确的模板。我需要的信息可能会在互联网上传播,但我很难自己拼凑出一个可行的解决方案。以下是上一个解决方案的复制粘贴,以便于阅读:
#include <iostream>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/at.hpp>
namespace mpl = boost::mpl;
template<int index1, int index2, int index3> void execKernel()
{
std::cout << "Kernel called with " << index1 << "/" << index2 << "/" << index3 << std::endl;
}
typedef void (*FPTR)();
FPTR ptr[512];
struct NIL
{
public:
static const int value = 0;
};
template<typename Seq, typename T1, typename T2 = NIL> class MakeSequenceImpl
{
public:
template<typename T> void operator()(T)
{
typedef MakeSequenceImpl<typename mpl::push_back<Seq,T>::type,T2> RunSeq;
mpl::for_each<T1>( RunSeq() );
}
};
template<typename Seq> class MakeSequenceImpl<Seq, NIL, NIL>
{
public:
template<typename T> void operator()(T)
{
typedef typename mpl::push_back<Seq,T>::type FinalSeq;
int index = mpl::at<FinalSeq,mpl::int_<0> >::type::value * 64
+ mpl::at<FinalSeq,mpl::int_<1> >::type::value * 8
+ mpl::at<FinalSeq,mpl::int_<2> >::type::value;
ptr[index] = execKernel<mpl::at<FinalSeq,mpl::int_<0> >::type::value, mpl::at<FinalSeq,mpl::int_<1> >::type::value, mpl::at<FinalSeq,mpl::int_<2> >::type::value>;
}
};
template<typename T0, typename T1, typename T2> class MakeSequence
{
public:
typedef mpl::vector_c<int> Seq;
MakeSequence()
{
typedef MakeSequenceImpl<Seq, T1, T2> RunSeq;
mpl::for_each<T0>( RunSeq() );
}
};
void callWrapper( int i, int j, int k )
{
ptr[i*64+j*8+k]();
}
typedef mpl::vector_c< int, 0, 1, 2, 3, 4, 5, 6, 7 > list1;
typedef mpl::vector_c< int, 0, 1, 2, 3, 4, 5, 6, 7 > list2;
typedef mpl::vector_c< int, 0, 1, 2, 3, 4, 5, 6, 7 > list3;
int main()
{
MakeSequence<list1,list2,list3> frontend;
int i,j,k;
std::cin >> i;
std::cin >> j;
std::cin >> k;
callWrapper(i,j,k);
}
我想概括一下将“execKernel”作为模板参数传递给“MakeSequence”。我有许多函数,如“execKernel”,所有函数都采用模板参数和相同类型的数量(所有函数都采用3个整数模板参数,0-7)。
为此,最后一个特化“MakeSequenceImpl&lt; Seq,NIL,NIL&gt;”中的运算符定义的最后一行需要在等号的两边进行推广。该语句的左侧是一个函数指针数组。我试图为所有函数推广这些函数采用相同的模板参数,但函数参数不同,因此需要以某种方式传递函数指针数组。在等号的右侧是函数模板实例化。需要为此部分传入特定的函数模板,但我发现如果不使用仿函数,则无法将未实例化的模板化函数作为模板参数传递。
总而言之,我希望将“MakeSequence”概括为概括,以便函数指针和函数模板本身的数组作为参数传递。我很高兴静态地为每个特定函数定义函数指针和函数指针数组。将它们概括一下也是很好的(例如,包含所有函数的所有函数指针的一个大的函数指针列表),但这是次要问题。
感谢任何人提供的任何帮助。顺便说一下,我需要继续使用C ++ 98/03和boost。没有C ++ 11或14。
答案 0 :(得分:1)
我通常会想到变种+访客:
<强> Live On Coliru 强>
#include <boost/variant.hpp>
// for demo types
#include <vector>
#include <iostream>
// some overloads and templates:
template <typename V>
void foo(std::vector<V> const&) { std::cout << __PRETTY_FUNCTION__ << "\n"; }
void foo(int) { std::cout << __PRETTY_FUNCTION__ << "\n"; }
void foo(std::string const&) { std::cout << __PRETTY_FUNCTION__ << "\n"; }
// a generic wrapper that instantiates 3 versions
// and picks the right one at runtime:
void generic_foo(boost::variant<std::string const&, int, std::vector<double> const&> param) {
// dispatch
boost::apply_visitor([](auto&& p) { foo(p); }, param);
}
int main() {
generic_foo("hello world");
generic_foo(std::vector<double> {0.1, 0.2, 0.3});
generic_foo(42);
}
打印
void foo(const string&)
void foo(const std::vector<_RealType>&) [with V = double]
void foo(int)
用更冗长的东西替换lambda:
namespace detail {
struct generic_foo_vis {
typedef void result_type;
template <typename T> void operator()(T const& stuff) const { return foo(stuff); }
template <typename T> void operator()(T& stuff) const { return foo(stuff); }
};
}
// a fixed wrapper that instantiates 3 versions and picks the right one at runtime:
void generic_foo(boost::variant<std::string const&, int, std::vector<double> const&> param) {
// dispatch
boost::apply_visitor(detail::generic_foo_vis(), param);
}