いくつかのメソッドを持つターゲット クラスがあるとします。
class Subject
{
public:
void voidReturn() { std::cout<<__FUNCTION__<<std::endl; }
int intReturn() { std::cout<<__FUNCTION__<<std::endl; return 137; }
};
そして Value クラス (コンセプトは Boost.Any に似ています):
struct Value
{
Value() {}
Value( Value const & orig ) {}
template< typename T > Value( T const & val ) {}
};
そして、Subject クラスのメソッドを使用して Value オブジェクトを生成したいと考えています。
Subject subject;
Value intval( subject.intReturn() );
Value voidVal( subject.voidReturn() ); // compilation error
VC++2008 で次のエラーが発生します。
error C2664: 'Value::Value(const Value &)' : cannot convert parameter 1 from 'void' to 'const Value &'
Expressions of type void cannot be converted to other types
および gcc 4.4.3:
/c/sandbox/dev/play/voidreturn/vr.cpp:67: error: invalid use of void expression
これのコンテキストは、テンプレート化されたクラス内で使用する場合です。
template< typename Host, typename Signature > class Method;
// Specialization for signatures with no parameters
template< typename Host, typename Return >
class Method< Host, Return () >
{
public:
typedef Return (Host::*MethodType)();
Method( Host * host, MethodType method ) : m_Host(host), m_Method(method) {}
Value operator()() { return Value( (m_Host->*m_Method)() ); }
private:
Host * m_Host;
MethodType m_Method;
};
何かを返すメソッド (つまり intReturn) でこの Method クラスを使用すると、次のようになります。
Method< Subject, int () > intMeth( &subject, &Subject::intReturn );
Value intValue = intMeth();
ただし、これを voidReturn メソッドで行うと:
Method< Subject, void () > voidMeth( &subject, &Subject::voidReturn );
Value voidValue = voidMeth();
上記と同様のエラーが発生します。
1 つの解決策は、メソッドを void 戻り値の型にさらに部分的に特殊化することです。
template< typename Host >
class Method< Host, void () >
{
public:
typedef void Return;
typedef Return (Host::*MethodType)();
Method( Host * host, MethodType method ) : m_Host(host), m_Method(method) {}
Value operator()() { return (m_Host->*m_Method)(), Value(); }
private:
Host * m_Host;
MethodType m_Method;
};
見た目が悪いだけでなく、すでに多くのコードの重複を伴う X 個のシグネチャ パラメータに対して Method クラスを特殊化し (Boost.Preprocessor がここで役立つことを願っています)、void 戻り型の特殊化を追加したいと考えています。その複製作業が 2 倍になるだけです。
void 戻り型のこの 2 番目の特殊化を回避する方法はありますか?