将调用链接到 C++ 中的临时变量
我有一个对字符串进行转换的类,就像这样
class transer{
transer * parent;
protected:
virtual string inner(const string & s) = 0;
public:
string trans(const string & s) {
if (parent)
return parent->trans(inner(s));
else
return inner(s);
}
transer(transer * p) : parent(p) {}
template <class T>
T create() { return T(this); }
template <class T, class A1> // no variadic templates for me
T create(A1 && a1) { return T(this, std::forward(a1)); }
};
我可以创建一个子类
class add_count : public transer{
int count;
add_count& operator=(const add_count &);
protected:
virtual string inner(const string & s) {
return std::to_string((long long)count++) + s;
}
public:
add_count(transer * p = 0) : transer(p), count(0) {}
};
然后我可以使用转换:
void use_transformation(transer & t){
t.trans("string1");
t.trans("string2");
}
void use_transformation(transer && t){
use_trasnformation(t);
}
use_transformation(add_count().create<add_count>());
是否有更好的设计?如果可以的话,我想避免使用动态分配/shared_ptr,但我不确定临时对象是否会在整个调用过程中保持活动状态。我还希望能够让每个 Transer 在销毁期间能够与其父级通信,因此临时对象也需要按正确的顺序销毁。创建链式转换并将其保存以供以后使用也很困难,因为
sometrans t = add_count().create<trans1>().create<trans2>().create<trans3>();
会保存指向不再存在的临时变量的指针。做类似的事情
trans1 t1;
trans2 t2(&t1);
trans3 t3(&t2);
很安全,但很烦人。有没有更好的方法来进行此类连锁操作?
I have a class that does a transformation on a string, like so
class transer{
transer * parent;
protected:
virtual string inner(const string & s) = 0;
public:
string trans(const string & s) {
if (parent)
return parent->trans(inner(s));
else
return inner(s);
}
transer(transer * p) : parent(p) {}
template <class T>
T create() { return T(this); }
template <class T, class A1> // no variadic templates for me
T create(A1 && a1) { return T(this, std::forward(a1)); }
};
So I can create a subclass
class add_count : public transer{
int count;
add_count& operator=(const add_count &);
protected:
virtual string inner(const string & s) {
return std::to_string((long long)count++) + s;
}
public:
add_count(transer * p = 0) : transer(p), count(0) {}
};
And then I can use the transformations:
void use_transformation(transer & t){
t.trans("string1");
t.trans("string2");
}
void use_transformation(transer && t){
use_trasnformation(t);
}
use_transformation(add_count().create<add_count>());
Is there a better design for this? I'd like to avoid using dynamic allocation/shared_ptr if I can, but I'm not sure if the temporaries will stay alive throughout the call. I also want to be able to have each transer
be able to talk to its parent during destruction, so the temporaries also need to be destroyed in the right order. It's also difficult to create a chained transformation and save it for later, since
sometrans t = add_count().create<trans1>().create<trans2>().create<trans3>();
would save pointers to temporaries that no longer exist. Doing something like
trans1 t1;
trans2 t2(&t1);
trans3 t3(&t2);
would be safe, but annoying. Is there a better way to do these kinds of chained operations?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
临时变量将在完整表达式结束时被销毁
与它们的构造顺序相反。小心后者,
但是,由于无法保证顺序
评估。 (当然,直接依赖除外:如果你
需要一个临时的来创建下一个——如果我已经
如果理解正确,那就是你的情况——那么你就安全了。)
Temporaries will be destructed at the end of the full expression, in the
reverse order they were constructed. Be careful about the latter,
however, since there are no guarantees with regards to the order of
evaluation. (Except, of course, that of direct dependencies: if you
need one temporary in order to create the next—and if I've
understood correctly, that's your case—then you're safe.)
如果您不想动态分配,则可以将操作的数据传递给启动链的函数,或者您需要一个根类型来保存它(除非您想要过度复制)。示例(可能无法编译):
首先,字符串位于从 startChain() 创建的临时 foo 上,所有链式操作都对该源数据进行操作。然后赋值最后将值复制到指定的 var 中。您几乎可以保证 startChain() 上的 RVO。
If you don't want dynamic allocation you either pass the data which is operated on to the function that initiates the chain, or you need a root type which holds it for you ( unless you want excessive copying ). Example ( might not compile ):
First the string lies on the temporary foo created from startChain(), all the chained operations operates on that source data. The assignment then at last copies the value over to the named var. You can probably almost guarantee RVO on startChain().