例外クラスの作成にマクロの代わりにテンプレートを使用できますか?
-
03-07-2019 - |
質問
新しい「例外」クラスを定義したいことがよくありますが、コンストラクターは継承されないため、適切なコンストラクターを定義する必要があります。
class MyException : public Exception
{
public:
MyException (const UString Msg) : Exception(Msg)
{
};
}
Typedefは、新しいクラスではなく単なるエイリアスであるため、これに対しては機能しません。現在、この些細な決まり文句の繰り返しを避けるために、私はロバワークを行う#defineを使用しています。
#define TEXCEPTION(T) class T : public Exception \
{ \
public:\
T(const UString Msg) : Exception(Msg) {}; \
}
...
TEXCEPTION(MyException);
しかし、これを達成するためのより良い方法があるかどうか疑問に思う-多分テンプレート、またはいくつかの新しいC ++ 0x機能
解決
テンプレートをパラメーターでパラメーター化するのではなく、例外から派生した新しいクラスが本当に必要な場合は、マクロを使用せずに引数を委任する独自のコンストラクターを記述する方法はありません。 C ++ 0xは、次のようなものを使用することで、必要な機能を備えています
class MyException : public Exception
{
public:
using Exception::Exception;
};
12.9" Inheriting Constructors"でその詳細を読むことができます(かなり多くの余分なルールがあるようです)。 C ++ 0xの最新ドラフト。
それまでは、ポリシーベースのデザインをお勧めします(OPはこのポリシーではなく上記を受け入れたため、小さなテキストを作成しました):
// deriving from Impl first is crucial, so it's built first
// before Exception and its Ctor can be used.
template<typename Impl>
struct ExceptionT : Impl, Exception {
// taking a tuple with the arguments.
ExceptionT(arg_types const& t = arg_types())
:Exception(Impl::Ctor(t)) { }
// taking a string. plain old stuff
ExceptionT(std::string const& s):Exception(Impl::Ctor(s)) { }
};
struct ExceptionDefImpl {
typedef boost::tuple<> arg_types;
// user defined ctor args can be done using a tuple
std::string Ctor(arg_types const& s) {
return std::string();
}
std::string const& Ctor(std::string const& s) {
return s;
}
};
// will inherit Ctor modifier from DefImpl.
struct MemoryLost : ExceptionDefImpl {
typedef boost::tuple<int> arg_types;
std::string Ctor(arg_types const& s) {
std::ostringstream os;
os << "Only " << get<0>(s) << " bytes left!";
return os.str();
}
int getLeftBytes() const { return leftBytes; }
private:
int leftBytes;
};
struct StackOverflow : ExceptionDefImpl { };
// alias for the common exceptions
typedef ExceptionT<MemoryLost> MemoryLostError;
typedef ExceptionT<StackOverflow> StackOverflowError;
void throws_mem() {
throw MemoryLostError(boost::make_tuple(5));
}
void throws_stack() { throw StackOverflowError(); }
int main() {
try { throws_mem(); }
catch(MemoryListError &m) { std::cout << "Left: " << m.getLeftBytes(); }
catch(StackOverflowError &m) { std::cout << "Stackoverflow happened"; }
}
他のヒント
整数でテンプレートクラスをパラメーター化できます:
#include <iostream>
#include <string>
using namespace std;
enum ExceptionId {
EXCEPTION_FOO,
EXCEPTION_BAR
};
class Exception {
string msg_;
public:
Exception(const string& msg) : msg_(msg) { }
void print() { cout << msg_ << endl; }
};
template <int T>
class TException : public Exception {
public:
TException(const string& msg) : Exception(msg) {};
};
void
foo()
{
throw TException<EXCEPTION_FOO>("foo");
}
void
bar()
{
throw TException<EXCEPTION_BAR>("bar");
}
int
main(int argc, char *argv[])
{
try {
foo();
} catch (TException<EXCEPTION_FOO>& e) {
e.print();
};
try {
bar();
} catch (TException<EXCEPTION_BAR>& e) {
e.print();
};
return 0;
}
ただし、実行時に設定/読み取りされる内部列挙を持つ単一のクラスを使用するよりも、なぜこれを優先するのかわかりません:
class TException {
public:
enum Type { FOO, BAR };
TException(Type type, const string& msg) : Exception(msg), type_(type) {}
Type type() const { return type_; }
private:
Type type_;
};
次に、TExceptionをキャッチしたときに型をオンにします...
// You could put this in a different scope so it doesn't clutter your namespaces.
template<struct S> // Make S different for different exceptions.
class NewException :
public Exception
{
public:
NewException(const UString Msg) :
Exception(Msg)
{
}
};
// Create some new exceptions
struct MyExceptionStruct; typedef NewException<MyExceptionStruct> MyException;
struct YourExceptionStruct; typedef NewException<YourExceptionStruct> YourException;
struct OurExceptionStruct; typedef NewException<OurExceptionStruct> OurException;
// Or use a helper macro (which kinda defeats the purpose =])
#define MAKE_EXCEPTION(name) struct name##Struct; typedef NewException<name##Struct> name;
MAKE_EXCEPTION(MyException);
MAKE_EXCEPTION(YourException);
MAKE_EXCEPTION(OurException);
// Now use 'em
throw new MyException(":(");
所属していません StackOverflow