我有一个对字符串进行转换的类,如此
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);
会安全,但很烦人。有没有更好的方法来进行这些链式操作?
答案 0 :(得分:4)
临终表演将在完整表达结束时被破坏 他们被构建的逆序。小心后者, 但是,由于没有关于订单的保证 评价。 (当然,直接依赖的除外:如果你 需要一个临时的,以便创建下一个 - 如果我已经 正确理解,这是你的情况 - 那么你是安全的。)
答案 1 :(得分:0)
如果您不想进行动态分配,您可以将操作的数据传递给启动链的函数,或者您需要一个根类型来保存它(除非您想要过多的复制)。示例(可能无法编译):
struct fooRef;
struct foo
{
fooRef create() { return fooRef( m_Val ); }
foo& operator=( const fooRef& a_Other );
std::string m_Val;
}
struct fooRef
{
fooRef( std::string& a_Val ) : m_Val( a_Val ) {}
fooRef create() { return fooRef( m_Val ); }
std::string& m_Val;
}
foo& foo::operator=( const fooRef& a_Other ) { m_Val = a_Other.m_Val; }
foo startChain()
{
return foo();
}
foo expr = startChain().create().create(); // etc
首先,字符串位于从startChain()创建的临时foo上,所有链接操作都对该源数据进行操作。然后,赋值最后将值复制到命名的var。你几乎可以在startChain()上保证RVO。