1

文字列を変換するクラスがあります。

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>());

このためのより良いデザインはありますか?可能であれば動的allocation/shared_ptrの使用を避けたいのですが、通話中に一時的なものが存続するかどうかはわかりません。また、破壊中にそれぞれが親と会話できるようにしたいtranserので、一時的なものも正しい順序で破壊する必要があります。連鎖変換を作成して後で使用するために保存することも困難です。

sometrans t = add_count().create<trans1>().create<trans2>().create<trans3>();

もはや存在しない一時的なものへのポインタを保存します。のようなことをする

trans1 t1;
trans2 t2(&t1);
trans3 t3(&t2);

安全ですが、迷惑です。このような連鎖操作を行うためのより良い方法はありますか?

4

2 に答える 2

4

一時的なものは、完全な表現の最後に、構築されたのとは逆の順序で破棄されます。ただし、後者については、評価の順序についての保証はありませんのでご注意ください。(もちろん、直接の依存関係の場合を除きます。次を作成するために一時的なものが必要な場合、そして私が正しく理解している場合は、それがあなたの場合です。そうすれば安全です。)

于 2011-09-27T16:22:44.350 に答える
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にあり、すべての連鎖操作はそのソースデータで動作します。次に、割り当ては最後に値を名前付き変数にコピーします。startChain()でRVOをほぼ保証できます。

于 2011-09-27T20:31:51.967 に答える