我正在实施一种类型T
。虽然这不是必需的,但此类用户可能会受到移动语义的影响,即T(T&&)
和T& operator=(T&&)
。
由于T
包含std::function
作为成员数据,我无法使用noexcept
保证实现移动语义,这会使T
更少对用户有用。
另外,由于上述原因,我的实施不能简单:T(&&) noexcept = default
和T& operator=(T&&) noexcept = default
另一种方法是向用户提供非noexcept
版本:T(&&) = default
和T& operator=(T&&) = default
;或者根据noexcept
(保证为std::function::swap()
)实现用户定义的noexcept
移动语义。在后一种情况下,遗憾的是我不得不处理std::function
以外的所有其他成员数据(丑陋!)。
所以,有三个选择:
T(&&) = default
和T& operator=(T&&) = default
T(&&) noexcept {/* lot of code */}
和T& operator=(T&&) noexcept {/* lot of code */}
我知道这个问题相当主观,但你会选择什么?
答案 0 :(得分:4)
假设您确实希望noexcept
移动,您可以通过以下方式减少选项#3的样板数量:
std::function
s ,或function
。它只需要使用swap实现move ctor和assignment操作符,并默认其他所有内容。好的,您还需要公开function
成员或转发函数调用操作符。答案 1 :(得分:0)
为什么不尝试将所有函数放在std :: vector中的std :: function中,然后交换向量?
vector有noexcept移动构造函数。
编辑:
为了完全扩展所需的概念,我无法在评论中回复。
对于您的情况(不同的功能签名),您将需要类型擦除和一些动态转换。
这里有一些代码,它们使用了所有陈述的概念(向量和枚举等)。
现在你可以保留你的lambda的矢量,无论签名如何。
class LambdaContainer
{
public:
struct GenericContainer {
virtual ~GenericContainer(){}
};
template <typename T>
struct SpecializedContainer : GenericContainer
{
SpecializedContainer(const T& t) : lambda(t){}
virtual ~SpecializedContainer(){}
T lambda;
};
private:
std::shared_ptr<GenericContainer> myLambda;
public:
template <typename T>
LambdaContainer(const T& aLambda) : myLambda(new SpecializedContainer<T>(aLambda)){}
std::shared_ptr<GenericContainer> getContainedLambda()
{
return myLambda;
}
};
enum eFunctions
{
FCT_INT=0,
FCT_FLOAT=1
};
...
int main()
{
int aa = 10;
float b = 3.0f;
std::function<void(int)> lambda1 = [aa](int arg)
{
printf("at this time b plus argument is %d\n ",aa+arg);
};
std::function<int (float, float )> lambda2 = [b] (float arg1, float arg2)
{ printf("calling the sum of floats %f , %f\n");
return (int)(arg1+arg2+b);};
std::vector<LambdaContainer> lambdaVector;
lambdaVector.push_back(LambdaContainer(lambda1));
lambdaVector.push_back(LambdaContainer(lambda2));
std::shared_ptr<LambdaContainer::GenericContainer> container = lambdaVector[FCT_INT].getContainedLambda();
LambdaContainer::SpecializedContainer<std::function<void(int)> >* ptr =
dynamic_cast<LambdaContainer::SpecializedContainer<std::function<void(int)> >*> (container.get());
if (ptr!=NULL)
{
std::function<void(int)> extractedLambda = ptr->lambda;
extractedLambda(5);
}
std::shared_ptr<LambdaContainer::GenericContainer> container2 = lambdaVector[FCT_FLOAT].getContainedLambda();
LambdaContainer::SpecializedContainer<std::function<int(float,float)> >* ptr2 =
dynamic_cast<LambdaContainer::SpecializedContainer<std::function<int(float,float)> >*> (container2.get());
if (ptr2!=NULL)
{
std::function<int(float,float)> extractedLambda = ptr2->lambda;
printf("the sum is %d\n",extractedLambda(3.0f,2.0f));
}
}