C++ C++;11可变模板&x2B;遗产
我想用可变模板写一个线性叠加的抽象。为此,我想定义一个基类型,它展示了某种形式的运算符(),如下所示C++ C++;11可变模板&x2B;遗产,c++,templates,c++11,inheritance,variadic-templates,C++,Templates,C++11,Inheritance,Variadic Templates,我想用可变模板写一个线性叠加的抽象。为此,我想定义一个基类型,它展示了某种形式的运算符(),如下所示 模板 类可叠加{ 公众: 类型定义结果\u t; void运算符()(结果和结果,常量参数和…)常量=0; }; 然后针对当前问题继承它,例如 class MyField : public Superposable<double, double, double> { public: void operator()(double& result, const do
模板
类可叠加{
公众:
类型定义结果\u t;
void运算符()(结果和结果,常量参数和…)常量=0;
};
然后针对当前问题继承它,例如
class MyField : public Superposable<double, double, double> {
public:
void operator()(double& result, const double& p1, const double& p2) const {
result = p1 + p2;
}
};
class MyField:公共可叠加{
公众:
void运算符()(双精度和结果、常数双精度和p1、常数双精度和p2)常数{
结果=p1+p2;
}
};
然后我想写一个抽象基类,它可以形成线性叠加,并得到可叠加的派生类作为模板参数,以确定operator()的调用签名。我想要点像这样的
template<typename S> // where S must be inherited from Superposable
class Superposition {
private:
std::vector< std::shared_ptr<S> > elements;
public:
// This is the problem. How do I do this?
void operator()(S::result_t& result, const S::Parameters&... parameters) const {
for(auto p : elements){
S::result_t r;
p->operator()(r, parameters);
result += r;
}
}
};
template//其中S必须从supplicatable继承
类叠加{
私人:
std::vector元素;
公众:
//这就是问题所在。我该怎么做?
void操作符(){
用于(自动p:元素){
S::结果r;
p->operator()(r,参数);
结果+=r;
}
}
};
以下是我的问题:
谢谢你的帮助 首先,直接解决您的问题 一些元编程样板:
template<class...>struct types{using type=types;};
叠加的主模板保留为空,默认参数提取可叠加的类型参数:
template<class S, class Args=extract_args_from<Superposable, S>>
class Superposition;
template<class S, class Result, class...Parameters>
class Superposition< S, types<Result, Parameters...>> {
。顺便说一句,你错过了一个虚拟的
请注意,我不赞成您的设计——结果应该是返回值(自然),使()
虚拟似乎是个坏主意(我会使用CRTP,如果我真的需要隐藏特定的实现,请键入erase)
您可以删除supplicatable
的主体,其工作原理如下:
public:
typedef Result result_t;
void operator()(Result& result, const Parameters&...) const = 0;
至少我建议你这么做
下一步是彻底摆脱继承和推断参数
:
class MyField {
public:
double operator()(const double& p1, const double& p2) const {
return p1 + p2;
}
};
template<typename S> // where S must be inherited from Superposable
class Superposition {
private:
std::vector< std::shared_ptr<S> > elements;
public:
template<class...Parameters,
class R=std::result_of_t<S&(Parameters const&...)>
>
R operator()(const Parameters&... parameters) const {
R ret = {};
for(auto p : elements){
ret += (*p)(parameters...);
}
return ret;
}
};
类MyField{
公众:
双运算符(){
返回p1+p2;
}
};
模板//其中S必须从Supplicatable继承
类叠加{
私人:
std::vector元素;
公众:
模板
R运算符()(常量参数和…参数)常量{
R ret={};
用于(自动p:元素){
ret+=(*p)(参数…);
}
返回ret;
}
};
它有完美转发的所有缺点,但也有所有的优点
std::result\u of t
是C++14,但在C++11中作为下拉菜单替换为typename std::result\u of::type
。模板
template <typename Result, typename... Parameters>
class Superposable
{
public:
using result_t = Result;
using params_t = std::tuple<Parameters...>;
virtual void operator()(Result& result, const Parameters&...) const = 0;
};
class MyField : public Superposable<double, double, double>
{
public:
void operator()(double& result, const double& p1, const double& p2) const
{
result = p1 + p2;
}
};
template <typename, typename>
class Superposition_impl;
template <typename S, std::size_t... Is>
class Superposition_impl<S, std::index_sequence<Is...>>
{
static_assert(std::is_base_of<Superposable<typename S::result_t, typename std::tuple_element<Is, typename S::params_t>::type...>, S>::value, "!");
public:
std::vector<std::shared_ptr<S>> elements;
void operator()(typename S::result_t& result, const typename std::tuple_element<Is, typename S::params_t>::type&... parameters) const
{
for (auto p : elements)
{
typename S::result_t r;
(*p)(r, parameters...);
result += r;
}
}
};
template <typename S>
using Superposition = Superposition_impl<S, std::make_index_sequence<std::tuple_size<typename S::params_t>::value>>;
类可叠加
{
公众:
使用结果\u t=结果;
使用params_t=std::tuple;
虚空运算符()(结果和结果,常量参数和…)常量=0;
};
类MyField:公共可叠加
{
公众:
void运算符()(双精度和结果、常数双精度和p1、常数双精度和p2)常数
{
结果=p1+p2;
}
};
模板
类叠加;
模板
类叠加
{
静态断言(std::是::value,“!”)的基础;
公众:
std::向量元素;
void操作符()
{
用于(自动p:元素)
{
typename S::result\u t r;
(*p)(r,参数…);
结果+=r;
}
}
};
模板
使用叠加=叠加\u impl;
感谢您的详细回答!当然,上面的Result和Parameters的double是更大对象的占位符,因此我希望避免按值返回。我显然需要更多地了解新的C++特性。你能推荐一些参考资料来阅读你使用的技巧吗?再次感谢。@SebastianBlatt按值返回几乎总是免费的,无论是实际的还是字面上的。要么通过省略(这只是很难保证),要么通过右值/移动构造函数(这几乎总是很容易)。它们是直接包含大型数组的类型吗?然后担心省略。否则,写一个move-ctor,并按值返回。
public:
typedef Result result_t;
void operator()(Result& result, const Parameters&...) const = 0;
class MyField {
public:
double operator()(const double& p1, const double& p2) const {
return p1 + p2;
}
};
template<typename S> // where S must be inherited from Superposable
class Superposition {
private:
std::vector< std::shared_ptr<S> > elements;
public:
template<class...Parameters,
class R=std::result_of_t<S&(Parameters const&...)>
>
R operator()(const Parameters&... parameters) const {
R ret = {};
for(auto p : elements){
ret += (*p)(parameters...);
}
return ret;
}
};
template <typename Result, typename... Parameters>
class Superposable
{
public:
using result_t = Result;
using params_t = std::tuple<Parameters...>;
virtual void operator()(Result& result, const Parameters&...) const = 0;
};
class MyField : public Superposable<double, double, double>
{
public:
void operator()(double& result, const double& p1, const double& p2) const
{
result = p1 + p2;
}
};
template <typename, typename>
class Superposition_impl;
template <typename S, std::size_t... Is>
class Superposition_impl<S, std::index_sequence<Is...>>
{
static_assert(std::is_base_of<Superposable<typename S::result_t, typename std::tuple_element<Is, typename S::params_t>::type...>, S>::value, "!");
public:
std::vector<std::shared_ptr<S>> elements;
void operator()(typename S::result_t& result, const typename std::tuple_element<Is, typename S::params_t>::type&... parameters) const
{
for (auto p : elements)
{
typename S::result_t r;
(*p)(r, parameters...);
result += r;
}
}
};
template <typename S>
using Superposition = Superposition_impl<S, std::make_index_sequence<std::tuple_size<typename S::params_t>::value>>;