【发布时间】:2010-09-06 02:04:17
【问题描述】:
假设你有一些目标类,上面有一些方法:
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();
产生与上述类似的错误。
一种解决方案是进一步对 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 返回类型只会使重复工作加倍。
是否有办法避免对 void 返回类型进行第二次特化?
【问题讨论】:
-
+1。我认为这是一个写得很好的问题。
标签: c++ templates generic-programming