これは少しOTですが、他の人を助けるためにここに置いておきたいと思いました。ここで私を導いたテンプレートの専門化についてグーグルで調べていましたが、@ maxim1000の答えは正解であり、最終的に私の問題を解決するのに役立ちましたが、それが十分に明確であるとは思いませんでした。
私の状況は、OPの状況とは少し異なります(ただし、この答えを残すのに十分似ています)。基本的に、私は「ステータスタイプ」を定義するあらゆる種類のクラスを持つサードパーティライブラリを使用しています。これらの型の中心は単にenum
sですが、クラスはすべて共通の(抽象的な)親から継承され、演算子のオーバーロードやstatic toString(enum type)
関数などのさまざまなユーティリティ関数を提供します。各ステータスenum
は互いに異なり、無関係です。たとえば、1 enum
つにはフィールド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
これが私の問題を解決するための理想的な解決策であるかどうかの手掛かりはありませんが、私にとってはうまくいきました。これで、使用する列挙型がいくつあってもtoString
、.cppファイルにメソッドの数行を追加するだけで、toString
自分で実装したり、それぞれを拡張したりせずに、定義済みのライブラリメソッドを使用できます。enum
使いたいクラス。