template< class T > struct ModuleNameTrait { static std::string Value() { return ""; } }; template< > struct ModuleNameTrait< Foo > { static std::string Value() { return "Foo"; } };
0
0
現在、ロギングライブラリにいくつかの機能を追加しています。 これらの1つは、クラスのモジュール名を宣言する可能性です。モジュール名は、そのクラス内からのログメッセージの書き込みに自動的に優先されます。 ただし、モジュール名が指定されていない場合、何も付加されません。 現在、名前を返す静的関数を持つtrait-classを使用しています。
template< class T > struct ModuleNameTrait { static std::string Value() { return ""; } }; template< > struct ModuleNameTrait< Foo > { static std::string Value() { return "Foo"; } };
このクラスは、ヘルパーマクロを使用して定義できます。 欠点は、モジュール名をクラス外で宣言する必要があることです。 これをクラス内で可能にしたいです。 また、プリプロセッサディレクティブを使用してすべてのログコードを削除できるようにしたいと考えています。 SFINAEを使用すると、テンプレート引数に特定のメンバーが含まれているかどうかを確認できますが、他の人は、私ほどテンプレートに慣れていないので、コードを維持する必要があるため、もっと簡単なソリューションを探しています。 何もなければ、私は特性アプローチに固執します。
前もって感謝します!
2 Answer
2
_ これをクラス内で可能にしたいです。 _
これはあなたのアプローチでは不可能であり、テンプレートがメンバーとなっている名前空間で明示的な特殊化を宣言する必要があります。
実際の使用コードがどのように見えるかは言いませんが、名前とオーバーロード解決があなたのために働くようにすることができるはずです(例: ロギングマクロから):
template const char* const name(const T&) { return ""; } class X; const char* const name(const X&) { return "X"; } struct X { // prints "X" void f() { std::cout << name(*this) << std::endl; } }; struct Y { static const char* const name(const Y&) { return "Y"; } // prints "Y" void f() { std::cout << name(*this) << std::endl; } }; struct Z { // prints "" void f() { std::cout << name(*this) << std::endl; } };
`name()`をクラスでのみ定義し、外部では定義したくない場合、もちろんテンプレートやオーバーロードは必要ありません:
const char* const name() { return ""; } struct X { static const char* const name() { return "X"; } // prints "X" void f() { std::cout << name() << std::endl; } }; struct Y { // prints "" void f() { std::cout << name() << std::endl; } };
0
ソリューションがどれほど単純かはわかりませんが、ここで何度か使用した非常に単純なものを紹介します。
次のような基本クラス `ClassName`があります。
class ClassName { string name; public: ClassName( string strName = "" ) : name(strName) { if( strName.length() ) strName += ": "; } string getName() { return name; } }; #ifdef _DEBUG #define LOG cout << getName() #else #define LOG cout #endif
そして、他のクラスはそれを継承し、その名前を与えます:
class Session : virtual public ClassName { public: Session() : ClassName("Session") { } void func() { LOG << "Some log here" << endl; } };