私たちのプロジェクトでは、表現する変数が何であるかを明示的に述べるためにかなりの "使用"を使用します。これは、主にstd::string
識別番号PortalId
またはCakeId
のように使用されます。今現在できることはC++とtypedefを使って強く型付けする
using PortalId = std::string;
using CakeId = std::string;
PortalId portal_id("2");
CakeId cake_id("is a lie");
portal_id = cake_id; // OK
です。私たちは好きではありません。 yum yumメソッドのほとんどを元のオブジェクトから保護しながら、リンゴとオレンジを混ぜないようにコンパイル時に型チェックをしたいと思います。
これは、C++での使用が次のものに近くなるように、割り当てが失敗し、マップやその他のものでそれを使用できるということですか?
SAFE_TYPEDEF(std::string, PortalId);
SAFE_TYPEDEF(std::string, CakeId);
int main()
{
PortalId portal_id("2");
CakeId cake_id("is a lie");
std::map<CakeId, PortalId> p_to_cake; // OK
p_to_cake[cake_id] = portal_id; // OK
p_to_cake[portal_id] = cake_id; // COMPILER ERROR
portal_id = cake_id; // COMPILER ERROR
portal_id = "1.0"; // COMPILER ERROR
portal_id = PortalId("42"); // OK
return 0;
}
我々はすでに、テンプレートと組み合わせて、いくつかのマクロを試してみましたが、私たちが必要な、非常に何を取得できませんでした。追加するには、C++ 14を使用することができます。
EDIT:我々が思いついたコードは醜い
あると動作しません
#define SAFE_TYPEDEF(Base, name) \
class name : public Base { \
public: \
template <class... Args> \
explicit name (Args... args) : Base(args...) {} \
const Base& raw() const { return *this; } \
};
ました。そして、それは動作しません私はコンパイラが
と大丈夫だったことを意味します。portal_id = cake_id;
EDIT2:explicit
というキーワードが追加されました。このコードでは、コードが実際にうまく動作します。これが正しい方法であるかどうか、それがすべての不幸な状況をカバーするかどうかは確かです。
まあ何も。 – Jendas
c-torの前に明示的に追加するだけです。 – firescreamer
これを文字列に対して行うと、その型を使用すると簡単に未定義の動作につながります: 'SAFE_TYPEDEF(std :: string、S); std :: string * s = new S(); delete s; '' std :: string'はベースクラスとして使用するためのものではありません。 – Jens