C++ 将表达式模板存储在 class 中,其对象将成为向量的一部分
C++ Store an expression template inside a class whose objects will be part of a vector
[为了清晰和拼写错误进行了大量编辑,现在尝试解决方案,旧版本在最后]
新版问题
我有一个 class 需要存储一个仿函数。问题在于仿函数是一个表达式模板(意味着每个仿函数都是不同类型的)。最重要的是,我需要将 class 的所有对象收集到一个向量中。
低于我的尝试:
我没有将仿函数的代码写成表达式模板,因为它太长了。因此,我将通过尝试存储两个不同 classes
的两个仿函数来测试代码
struct FunctorTypeA {
double a;
FunctorTypeA(const double ap): a(ap) {}
double operator()(const double x){ return a;}
};
struct FunctorTypeB {
double a, b;
FunctorTypeB(const double ap, const double bp): a(ap), b(bp) {}
double operator()(const double x){ return a+b*x;}
};
我认为,如果我错了请纠正我,如果下面的代码适用于上面的两个仿函数,它应该适用于任何使用表达式模板构造的仿函数。
第一个想法是
template <typename functorType> struct myClass {
functorType functor;
myClass(functorType funct): functor(funct){}
};
我可以将仿函数存储在 class 的对象中,其中:
FunctorTypeA functor1(1.2);
FunctorTypeB functor2(1.5, 5.0);
myClass myObj1(functor1);
myClass myObj2(functor2);
cout << myObj1.functor(0.2) << " " << myObj1.functor(0.2) << "\n\n";
但是我无法将这些对象存储在 std::vector
中,因为它们具有不同的类型。
因此我尝试了:
struct myClass2Base {
virtual ~TrialClassBase() = default;
virtual double functor(const double x) = 0;
};
template <typename functorType> struct myClass2 : public myClass2Base {
functorType functorStored;
myClass2(functorType funct): functorStored(funct){}
double functor(const double x){return functorStored(x);}
};
并且我可以构建这些对象的矢量作为
std::vector<myClass2Base*> vecOfObj;
vecOfObj.push_back(new myClass2(functor1));
cout << vecOfObj[0]->functor(0.3) << "\n\n";
这个有效。
有更好的解决方案吗?
谢谢!
旧版问题
我有一个 class 需要存储一个仿函数,它是一个表达式模板(意味着每个函数都是不同类型的)。我还需要将 class 的对象放在 std::vector.
中
我的尝试是
struct TrialClassBase{
virtual double get_functor(double) = 0;
};
template <typename derived> struct TrialClass : public TrialClassBase {
derived functor;
TrialClass(derived fun): functor(fun){}
double get_functor(double x) {return functor(x);}
};
std::vector<shared_ptr<TrialClassBase>> vecOfObjs;
然后我尝试向矢量添加一个对象。作为示例,我使用 std::function,仅作为示例:在我的例子中,仿函数将是一个表达式模板。
std::function<double(double)> funcccc = [](double x){return x*x;};
vecc.emplace_back(TrialClass(funcccc));
cout << vecc[0]->get_functor(0.3) <<"\n\n";
编译失败。我犯了什么错误?我怎样才能做我想做的事?
谢谢!
您构建的 shared_ptr
无效
正如评论中指出的那样:
- 一个基class应该总是有一个虚拟析构函数
push_back
优先
struct TrialClassBase {
virtual double get_functor(double) = 0;
virtual ~TrialClassBase() = default;
};
template <typename derived> struct TrialClass : public TrialClassBase {
derived functor;
TrialClass(derived fun) : functor(fun) {
}
double get_functor(double x) {
return functor(x);
}
};
std::vector<std::shared_ptr<TrialClassBase>> vecc;
int main() {
std::function<double(double)> funcccc = [](double x) { return x * x; };
vecc.push_back(
std::make_shared<TrialClass<std::function<double(double)>>>(funcccc));
std::cout << vecc[0]->get_functor(0.3) << "\n\n";
}
我看到你改进了你的问题。
是的,有更好的解决方案。
std 库为您提供的一个很好的解决方案是使用类型擦除 std:function
。
#include <vector>
#include <functional>
#include <iostream>
#include <cmath>
struct FunctorTypeA {
double a;
FunctorTypeA(const double ap): a(ap) {}
auto operator()([[maybe_unused]]const double x) const { return a;}
};
int main(){
auto funcVec{std::vector<std::function<double(double)>>{}};
funcVec.push_back(FunctorTypeA{3.14}); // functor allowed
funcVec.push_back([](double x){return x;}); // lambda allowed
funcVec.push_back(sqrt); // function pointer allowed, e.g. C math function
for(auto&& f:funcVec){
std::cout << f(2.0) << '\n';
}
}
这样您就不会将继承和指针转换复杂化。那里容易出错。 std::vector
和 std::function
将完成所有清理工作。 (这是您在指针向量解决方案中很容易错过的东西)
注意:std::function
可能会执行动态分配。但是 std::vector
也是如此,并且继承有 vtable 开销。
[为了清晰和拼写错误进行了大量编辑,现在尝试解决方案,旧版本在最后]
新版问题
我有一个 class 需要存储一个仿函数。问题在于仿函数是一个表达式模板(意味着每个仿函数都是不同类型的)。最重要的是,我需要将 class 的所有对象收集到一个向量中。
低于我的尝试:
我没有将仿函数的代码写成表达式模板,因为它太长了。因此,我将通过尝试存储两个不同 classes
的两个仿函数来测试代码struct FunctorTypeA {
double a;
FunctorTypeA(const double ap): a(ap) {}
double operator()(const double x){ return a;}
};
struct FunctorTypeB {
double a, b;
FunctorTypeB(const double ap, const double bp): a(ap), b(bp) {}
double operator()(const double x){ return a+b*x;}
};
我认为,如果我错了请纠正我,如果下面的代码适用于上面的两个仿函数,它应该适用于任何使用表达式模板构造的仿函数。
第一个想法是
template <typename functorType> struct myClass {
functorType functor;
myClass(functorType funct): functor(funct){}
};
我可以将仿函数存储在 class 的对象中,其中:
FunctorTypeA functor1(1.2);
FunctorTypeB functor2(1.5, 5.0);
myClass myObj1(functor1);
myClass myObj2(functor2);
cout << myObj1.functor(0.2) << " " << myObj1.functor(0.2) << "\n\n";
但是我无法将这些对象存储在 std::vector
中,因为它们具有不同的类型。
因此我尝试了:
struct myClass2Base {
virtual ~TrialClassBase() = default;
virtual double functor(const double x) = 0;
};
template <typename functorType> struct myClass2 : public myClass2Base {
functorType functorStored;
myClass2(functorType funct): functorStored(funct){}
double functor(const double x){return functorStored(x);}
};
并且我可以构建这些对象的矢量作为
std::vector<myClass2Base*> vecOfObj;
vecOfObj.push_back(new myClass2(functor1));
cout << vecOfObj[0]->functor(0.3) << "\n\n";
这个有效。 有更好的解决方案吗?
谢谢!
旧版问题
我有一个 class 需要存储一个仿函数,它是一个表达式模板(意味着每个函数都是不同类型的)。我还需要将 class 的对象放在 std::vector.
中我的尝试是
struct TrialClassBase{
virtual double get_functor(double) = 0;
};
template <typename derived> struct TrialClass : public TrialClassBase {
derived functor;
TrialClass(derived fun): functor(fun){}
double get_functor(double x) {return functor(x);}
};
std::vector<shared_ptr<TrialClassBase>> vecOfObjs;
然后我尝试向矢量添加一个对象。作为示例,我使用 std::function,仅作为示例:在我的例子中,仿函数将是一个表达式模板。
std::function<double(double)> funcccc = [](double x){return x*x;};
vecc.emplace_back(TrialClass(funcccc));
cout << vecc[0]->get_functor(0.3) <<"\n\n";
编译失败。我犯了什么错误?我怎样才能做我想做的事?
谢谢!
您构建的 shared_ptr
无效
正如评论中指出的那样:
- 一个基class应该总是有一个虚拟析构函数
push_back
优先
struct TrialClassBase {
virtual double get_functor(double) = 0;
virtual ~TrialClassBase() = default;
};
template <typename derived> struct TrialClass : public TrialClassBase {
derived functor;
TrialClass(derived fun) : functor(fun) {
}
double get_functor(double x) {
return functor(x);
}
};
std::vector<std::shared_ptr<TrialClassBase>> vecc;
int main() {
std::function<double(double)> funcccc = [](double x) { return x * x; };
vecc.push_back(
std::make_shared<TrialClass<std::function<double(double)>>>(funcccc));
std::cout << vecc[0]->get_functor(0.3) << "\n\n";
}
我看到你改进了你的问题。 是的,有更好的解决方案。
std 库为您提供的一个很好的解决方案是使用类型擦除 std:function
。
#include <vector>
#include <functional>
#include <iostream>
#include <cmath>
struct FunctorTypeA {
double a;
FunctorTypeA(const double ap): a(ap) {}
auto operator()([[maybe_unused]]const double x) const { return a;}
};
int main(){
auto funcVec{std::vector<std::function<double(double)>>{}};
funcVec.push_back(FunctorTypeA{3.14}); // functor allowed
funcVec.push_back([](double x){return x;}); // lambda allowed
funcVec.push_back(sqrt); // function pointer allowed, e.g. C math function
for(auto&& f:funcVec){
std::cout << f(2.0) << '\n';
}
}
这样您就不会将继承和指针转换复杂化。那里容易出错。 std::vector
和 std::function
将完成所有清理工作。 (这是您在指针向量解决方案中很容易错过的东西)
注意:std::function
可能会执行动态分配。但是 std::vector
也是如此,并且继承有 vtable 开销。