これは少しOTですが、他の誰かに役立つ場合に備えて、ここに残しておくと思いました。私はここに私を導いたテンプレートの特殊化についてグーグルで調べていました。@maxim1000の答えは正しく、最終的には私の問題を理解するのに役立ちましたが、それが十分に明確であるとは思いませんでした。
私の状況はOPの状況とは少し異なります(しかし、私が思うにこの答えを残すのに十分似ています)。基本的に、私は「ステータスタイプ」を定義するすべての異なる種類のクラスを持つサードパーティライブラリを使用しています。これらのタイプの中心は単純ですenum
が、クラスはすべて共通の(抽象的な)親から継承し、演算子のオーバーロードや関数などのさまざまなユーティリティ関数を提供しstatic toString(enum type)
ます。それぞれのステータスenum
は互いに異なり、無関係です。たとえば、1enum
つにはフィールドがありNORMAL, DEGRADED, INOPERABLE
、もう1つにはフィールドがありますAVAILBLE, PENDING, MISSING
。私のソフトウェアは、さまざまなコンポーネントのさまざまなタイプのステータスの管理を担当しています。toString
これらの機能を活用したいと思ったのですenum
クラスですが、抽象的であるため、直接インスタンス化することはできませんでした。使用したい各クラスを拡張することもできましたが、最終的には、気になる具体的なステータスが何であれtemplate
、クラスを作成することにしました。その決定についてはおそらく議論の余地がありますが、それは、各抽象クラスを独自のカスタムクラスで拡張して抽象関数を実装するよりもはるかに少ない作業であると感じました。そしてもちろん、私のコードでは、呼び出して、その文字列表現を出力できるようにしたかっただけです。すべてが完全に無関係だったので、それぞれが独自のものを持っていましたtypename
enum
enum
.toString(enum type)
enum
enum
toString
(私が学んだいくつかの調査の後で)テンプレートの特殊化を使用して呼び出さなければならなかった関数。それが私をここに導きました。以下は、これを正しく機能させるために私がしなければならなかったことのMCVEです。実際、私のソリューションは@maxim1000のソリューションとは少し異なっていました。
これは、の(非常に単純化された)ヘッダーファイルですenum
。実際には、各enum
クラスは独自のファイルで定義されていました。このファイルは、私が使用しているライブラリの一部として提供されているヘッダーファイルを表しています。
// file enums.h
#include <string>
class Enum1
{
public:
enum EnumerationItem
{
BEARS1,
BEARS2,
BEARS3
};
static std::string toString(EnumerationItem e)
{
// code for converting e to its string representation,
// omitted for brevity
}
};
class Enum2
{
public:
enum EnumerationItem
{
TIGERS1,
TIGERS2,
TIGERS3
};
static std::string toString(EnumerationItem e)
{
// code for converting e to its string representation,
// omitted for brevity
}
};
次のファイルを別のコードブロックに分割するためだけにこの行を追加します。
// file TemplateExample.h
#include <string>
template <typename T>
class TemplateExample
{
public:
TemplateExample(T t);
virtual ~TemplateExample();
// this is the function I was most concerned about. Unlike @maxim1000's
// answer where (s)he declared it outside the class with full template
// parameters, I was able to keep mine declared in the class just like
// this
std::string toString();
private:
T type_;
};
template <typename T>
TemplateExample<T>::TemplateExample(T t)
: type_(t)
{
}
template <typename T>
TemplateExample<T>::~TemplateExample()
{
}
次のファイル
// file TemplateExample.cpp
#include <string>
#include "enums.h"
#include "TemplateExample.h"
// for each enum type, I specify a different toString method, and the
// correct one gets called when I call it on that type.
template <>
std::string TemplateExample<Enum1::EnumerationItem>::toString()
{
return Enum1::toString(type_);
}
template <>
std::string TemplateExample<Enum2::EnumerationItem>::toString()
{
return Enum2::toString(type_);
}
次のファイル
// and finally, main.cpp
#include <iostream>
#include "TemplateExample.h"
#include "enums.h"
int main()
{
TemplateExample<Enum1::EnumerationItem> t1(Enum1::EnumerationItem::BEARS1);
TemplateExample<Enum2::EnumerationItem> t2(Enum2::EnumerationItem::TIGERS3);
std::cout << t1.toString() << std::endl;
std::cout << t2.toString() << std::endl;
return 0;
}
そしてこれは出力します:
BEARS1
TIGERS3
これが私の問題を解決するための理想的な解決策であるかどうかはわかりませんが、それは私にとってはうまくいきました。これで、使用する列挙型の数に関係なく、.cppファイルにメソッドの数行を追加するだけで、自分で実装したり、それぞれを拡張したりすることなくtoString
、ライブラリの定義済みメソッドを使用できます。使いたいクラス。toString
enum