我正在研究类似管道的设计模式。我的设计目标之一是通过提供指向某个数据类的函数成员的指针来启用管道段的动态链接。
每个数据类都有一组使用整数模板参数索引的函数成员(代表数据类输出端口)。这些函数使用关键字动态推断返回类型auto
,但都接受相同的整数参数c_Idx
,即template <int N> auto getOutput(int c_Idx) const
。与每个功能相关的功能getOutput
是(由用户)在一组部分专用的结构中定义的getOutputImpl
。因此,每个数据类可以具有从 1 个到某个固定数量K
的输出数据端口。
为了允许以通用方式在管道段之间进行动态链接,可以将它们存储在 类型的容器中std::vector<boost::any>
。但是,我需要能够用指向函数成员模板的指针自动填充这个向量。
手动实现的示例如下所示
template<class TLeafType>
class AlgorithmOutput
{
protected:
std::vector<boost::any> OutputPorts;
public:
AlgorithmOutput()
{
//////////////////////////////////////////
// This procedure needs to be automated //
//////////////////////////////////////////
std::function<std::unique_ptr<double>(int)> pOutFun1 = std::bind(
std::mem_fn(
true ? &AlgorithmOutput<TLeafType>::getOutput<0> : nullptr
),
this,
std::placeholders::_1
);
OutputPorts.push_back(pOutFun1);
std::function<std::unique_ptr<int>(int)> pOutFun2 = std::bind(
std::mem_fn(
true ? &AlgorithmOutput<TLeafType>::getOutput<1> : nullptr
),
this,
std::placeholders::_1
);
OutputPorts.push_back(pOutFun2);
}
virtual ~AlgorithmOutput() {}
protected:
TLeafType* asLeaf(void)
{
return static_cast<TLeafType*>(this);
}
TLeafType const* asLeaf(void) const
{
return static_cast<TLeafType const*>(this);
}
public:
template <int N>
auto getOutput(int c_Idx) const
{
return asLeaf() -> getOutput<N>(c_Idx);
}
boost::any getOutputPort(int PortIdx)
{
return OutputPorts[PortIdx];
}
};
class PipeOutputClass: public AlgorithmOutput<PipeOutputClass>
{
public:
template <int N>
auto getOutput(int c_Idx) const
{
return getOutputImpl<N>::apply(this, c_Idx);
}
template<int N, typename S> friend struct getOutputImpl;
template<int N, typename = void>
struct getOutputImpl
{
static auto apply(
PipeOutputClass const* p_Self,
int c_Idx
)
{ throw std::runtime_error("Wrong template argument."); }
};
template <typename S>
struct getOutputImpl<0, S>
{
static std::unique_ptr<double> apply(
PipeOutputClass const* p_Self,
int c_Idx
)
{
std::unique_ptr<double> mydouble(new double(10));
return mydouble;
}
};
template <typename S>
struct getOutputImpl<1, S>
{
static std::unique_ptr<int > apply(
PipeOutputClass const* p_Self,
int c_Idx
)
{
std::unique_ptr<int > myint(new int(3));
return myint;
}
};
};
上面例子的问题是我pOutFunX
手动定义了成员函数指针,而我想自动化这个过程。
请注意,我不考虑与上述设计有显着差异的设计解决方案。
在这里,我提出了一些关于解决这个问题的可能方法的一些想法。我为我目前正在考虑的解决方案制定了一个计划,如果您尝试回答这个问题,这可能会有用:
- 获取名为 的用户定义的部分专用结构的数量
getOutputImpl
。 - 对于每个这样的结构,确定其名为 的成员的输出类型
apply
。 - 设置一个(递归)元模板过程,该过程创建指向具有相关签名的函数的指针并将它们添加到
OutputPort
向量中。
我假设上面的步骤 1-3 都必须在编译时完成。如果不需要用户设计数据输出类的任何干预,我不关心解决方案的美观性。但是,我不希望使用自定义编译器宏。
这篇文章展示了如何推断成员函数签名,这可能很有用。