3

以前に 9000 回以上回答された可能性のある質問がありますが、それをどのように表現すればよいかわかりません。これを試してみます

いくつかの C++ の書籍やチュートリアルで、反復可能な値 (インクリメント可能な) セマンティクスを持つ独自のクラスを定義するときに、そのクラスをオーバーロードできることを見てきましoperator++た (ここで述べていることはすべて、同様に当てはまると思いますoperator--)。これを行う標準的な方法は次のようです。

class MyClass {
    public:
    MyClass& operator++ () {
        increment_somehow();
        return *this;
        }
    ....
    };

まあincrement_somehow()...どういうわけかオブジェクトの値を増やします。

operator++次に、次のような方法での後置バージョンを定義できます。

MyClass operator++ (MyClass& it, int dummy) {
    MyClass copy(it);
    ++it;
    return copy;
    }

それはすべてうまくいきます(私はそのイディオムを正しく理解したと思います)が、問題は、operator++すばやく定義するクラスごとにすべてを行うのは面倒で冗長になることです。演算子をオーバーロードするときに最近学びました。つまり、昨日知った<utility>ヘッダーと内部の機能を利用することです ( 4年間離れてから C++ に戻ってきたばかりです...):rel_ops

class MyClass {
    public:
    bool operator== (const MyClass& that) {
        return compare_for_equality_somehow(that);
        }
    bool operator< (const MyClass& that) {
        return compare_for_lessality_somehow(that);
        }
    ....
    using namespace std::rel_ops; // operators >, >=, <=, ! are "magically" defined!
    };

(類推の目的で「劣性」という用語を発明したところですが、私の頭は何らかの理由で正しい数学用語を思いつくことを拒否しています...)

Utility ヘッダーにある名前空間<step_ops.hpp>をいくらか模倣した内容の単純なヘッダーを作成しました。std::rel_ops数回のコンパイル後に私が見ることができるものから、それはただ動作します(TM)。このトリックを使用できますか / 使用する必要がありますか? using namespace MyLibrary::increment_operatorsクラスを作成して(たとえば)を使用する場合に遭遇する可能性のある落とし穴は何ですか?

そして、おそらくもっと重要なことは、車輪を再発明しただけなのか、それとも、そのような種類のプロジェクトに集約できる便利な小さなライブラリを作成しただけなのかということです。C++ を使って自分自身を最新の状態に戻し、共同作業を行うために試みたほとんどすべての実験は、すでにboost::do_something施設の下でカバーされているようで、長い時間を費やしてしまったことを悲しく思います。

4

4 に答える 4

4

Boost は、 Boost Operatorsユーティリティ ライブラリでこの機能を提供します。その実装は少し異なりますが、同じ結果が得られます。

このトリックを使用できますか / 使用する必要がありますか?

可能な限り使用してください。冗長で反復的なコードを削除することは、リファクタリングの基本原則であり、実践するのに適した方法です。

もう一度車輪を再発明したのでしょうか、それとも、そのような種類のプロジェクトに集約できる便利な小さなライブラリを作成したのでしょうか?

車輪を再発明したと言えるでしょう。とはいえ、それが必ずしも悪いことだとは思いません。自分で何かを実装すると、通常はそれをよりよく理解し、プロセスを通じて多くのことを学ぶことができます。

于 2010-07-14T00:30:00.767 に答える
1

時間に余裕があり、経験が必要な場合は、好きな車輪をすべて再発明してください。根底にある概念の知識を向上させるために、私は自分でいくつかのことをしました。それは大いに役立ちます。

于 2010-07-14T00:38:40.970 に答える
0

または<template T>、C++言語に組み込まれているものを使用することもできます。同じコードに複数の型を使用できます。必要なのは、クラスで新しく定義された演算子を使用するクラスごとに、templateすべてのメソッドが定義されていることを確認することだけです。 .

http://www.cplusplus.com/doc/tutorial/templates/の詳細については、ドキュメントを参照してください。template

于 2010-07-14T00:36:32.990 に答える
0

私は元の投稿者で、最終的に StackOverflow に登録したと答えただけです。ということで、ハンドルを新しくしました。答え、特にモチベーションの問題を抱えた HeadGeek に感謝します。また、自分自身を修正し、tjm のコメントに従ってください。コードが使用されている正確な形式は、私が投稿したものとは異なります。このメソッドを使用するより正しい方法は、次の方法で各演算子をクラス独自のスコープに持ち込むことusingです。

namespace scope {
class MyClass {
  public:
  bool operator== (const MyClass& that) {
    return compare_for_equality_somehow(that);
    }
  bool operator< (const MyClass& that) {
    return compare_for_lessality_somehow(that);
    }
  ....
  // using namespace std::rel_ops; // that one is incorrect
  };
using std::rel_ops::operator=!; // similarly for >, >=, <=
} // end of namespace

私の元の投稿のように実行すると、ヘッダーは正常にコンパイルされますが、ヘッダーが含まれているプロジェクトに含まれているとコンパイルエラーが発生しますrel_ops。さらに重要なことは、そのメソッドは、クラスのスコープで定義されたすべてのクラスのすべての演算子をもたらすことです。これは明らかに望ましくありません。この明示的なアプローチでは、必要な演算子のみがスコープに取り込まれ、必要に応じて解決されます。using

皆さん、ありがとうございます。

また、提供するものがあると本当に感じない限り、この質問に賛成票を投じないでください-Boostにはすでにあるので新しいものではありません-私はこれを二重の有益な目的で投稿しました

于 2010-08-10T22:04:14.130 に答える