1

数学演算をラップするクラスがあるとします。おもちゃの例を使ってみましょう

class Test
{
public:
   Test( float f ) : mFloat( f ), mIsInt( false ) {}

   float mFloat;
   int   mInt;
   bool  mIsFloat;
};

次のプロトタイプを使用して、演算子のオーバーロードを作成したいと思います。

float operator=( const Test& test ) 
{ 
    if ( !test.mIsFloat ) return *this; // in this case don't actually do the assignment
    return test.mFloat;                      // in this case do it.
} 

私の質問は次のとおりです。組み込みの戻り値の型で operator= をオーバーロードできますか? もしそうなら、組み込み型を参照する方法はありますか?

ビルトインをクラスでラップすれば、これができることはわかっています。しかし、この場合、代入演算子を LHS の組み込み型で動作させたいと考えています。

使用例:

Test t( 0.5f );
float f = t; // f == 0.5
int   i = 0;
i = t;       // i stays 0.

更新: 助けてくれてありがとう。おもちゃの例から少し拡張して、私が実際にやろうとしていることを人々が理解できるようにします。

さまざまなタイプのパラメーターのツリーから構成パラメーターを取得できる構成システムがあります(整数、浮動小数点数、文字列、配列などにすることができます)。

次のような操作でツリーからアイテムを取得できます。

float updateTime = config["system.updateTime"];

ただし、「system.updateTime」が存在しない可能性があります。または、タイプが間違っています。一般に、構成にはデフォルトのブロックがあり、構成からデフォルトをオーバーライドするコードがあります。

float updateTime = 10;
const char* logFile = "tmp.log";
... etc etc...

私は次のようなことをしたい:

updateTime = config["system.updateTime"];

オーバーライドがある場合に操作が成功する場所。そのため、通常、operator[] からの戻り値がツリー内の「無効な」ノードである場合、割り当ては行われません。

今、私は次のような関数でそれを解決します:

getConfig( config, "system.updateTime", updateTime );

しかし、代入演算子を使用したいと思います。

ビルトインをラップするクラスを作成したい場合は、これを行うことができます。

class MyFloat
{
   operator=( const Test& test ) { if (test.isValidNode() ) f = test.float(); return *this; }
   float f;
}

しかし、割り当てをオーバーロードするためだけに、ビルトインを自明なクラスでラップしない方がよいことは明らかです。質問は - これは c++ で可能ですか?

4

4 に答える 4

3

あなたの例に基づいて、あなたが本当に欲しいのは暗黙の変換演算子です:

class Test
{
    // ...
public:
    operator float() const;
};

inline Test::operator float() const
{
    return mIsFloat ? mFloat : mInt;
}

条件付きで割り当てを行いたい場合は、別のアプローチを取る必要があります。すべてのことを考慮して、名前付きメソッドがおそらく最良のオプションです...次のようなものです:

class Test
{
public:
    bool try_assign(float & f) const;
};

inline bool Test::try_assign(float & f) const
{
    if (mIsFloat) {
        f = mFloat;
    }

    return mIsFloat;
}

何をするにしても、導入したシンタックス シュガーによってコードが判読不能にならないように注意してください。

于 2012-10-30T17:45:46.287 に答える
1

テンプレートの特殊化の使用:

class Config {
    template<typename T>
    void setValue(const std::string& index, T& value); //sets the value if available
};

template<float>
void Config::setValue(const std::string& index, float& value){...} //only sets float values

template<int>
void Config::setValue(const std::string& index, int& value){...} //only sets int values;
于 2012-10-30T18:42:02.797 に答える
1

変換コンストラクターの形式で、からfloatへの暗黙的な変換が既に 1 つあります。Test

class Test
{
public:
 /* ... */
Test( float f ) : mFloat( f ) /*...*/ {}       

};

次のような変換をサポートします。

Test t(0.5f);

floatから へのさらに暗黙的な変換をTest可能にするために、コピー代入演算子も必要になるでしょう。

class Test
{
public:

    Test& operator=(float f) { mFloat = f; return *this; }  
};

t = 0.75; // This is possible now

Testからへの暗黙的な変換をサポートするために、floatは使用しませんoperator=が、次のように宣言および実装されたカスタム キャスト演算子を使用します。

class Test
{
public:
  /* ... */
  operator float () const { return mFloat; }
};

これにより、次のような暗黙的な変換が可能になります。

float f = t;

余談ですが、ここで別の暗黙の変換が行われていることに気付いていないかもしれません。このコードでは:

Test t( 0.5 );

リテラル値0.5は ではなくfloatですdouble。convert コンストラクターを呼び出すには、この値を に変換する必要がありますfloat。これにより、精度が失われる可能性があります。floatリテラルを指定するには、f接尾辞を使用します。

Test t( 0.5f );
于 2012-10-30T17:51:19.803 に答える
0

基本タイプの演算子を「オーバーロード/追加」することはできませんが、タイプについてはできますType。しかし、これはただではありませんoperator =- operator >>sのようにistream

class Test
{
public:
   float mFloat;
   int   mInt;
   bool  mIsFloat;
   Test& operator >> (float& v) { if (mIsFloat) v = mFloat; return *this; }
   Test& operator >> (int& v) { if (!mIsFloat) v = mInt; return *this; }
};

次に、次のことができます。

int main() {
  float v = 2;
  Test t = { 1.0, 2, false };
  t >> v; // no effect
  t.mIsFloat = true;
  t >> v; // now v is changed
}   

アップデート

私は次のようなことをしたい:

updateTime = config["system.updateTime"];

それから私の提案で、あなたはカム:

config["system.updateTime"] >> updateTime;
于 2012-10-30T17:48:24.600 に答える