[英]void return value from a function used as input to a templated function is seen as a parameter
Say you have some target class with some methods on it: 假设您有一些目标类,其中包含一些方法:
class Subject
{
public:
void voidReturn() { std::cout<<__FUNCTION__<<std::endl; }
int intReturn() { std::cout<<__FUNCTION__<<std::endl; return 137; }
};
And a Value class (similar in concept to Boost.Any): 和Value类(概念类似于Boost.Any):
struct Value
{
Value() {}
Value( Value const & orig ) {}
template< typename T > Value( T const & val ) {}
};
And I want to produce a Value object using a method from the Subject class: 我想使用Subject类中的方法生成一个Value对象:
Subject subject;
Value intval( subject.intReturn() );
Value voidVal( subject.voidReturn() ); // compilation error
I get the following errors in VC++2008: 我在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
and gcc 4.4.3: 和gcc 4.4.3:
/c/sandbox/dev/play/voidreturn/vr.cpp:67: error: invalid use of void expression
The context for this is when you want to use it inside a templated class: 这个上下文是你想在模板化的类中使用它的时候:
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;
};
Using this Method class on the method which returns something (namely intReturn) would look like: 在返回某些东西的方法(即intReturn)上使用此Method类看起来像:
Method< Subject, int () > intMeth( &subject, &Subject::intReturn );
Value intValue = intMeth();
However, doing this with the voidReturn method: 但是,使用voidReturn方法执行此操作:
Method< Subject, void () > voidMeth( &subject, &Subject::voidReturn );
Value voidValue = voidMeth();
yields similar errors as above. 产生与上述类似的错误。
One solution is to further partially specialize Method for void return types: 一种解决方案是进一步部分地专门化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;
};
Besides it just feeling ugly, I'm also wanting to specialize the Method class for X numbers of signature parameters, which already involves a lot of code duplication (hopefuly Boost.Preprocessor can help here), and then adding a specialization for void return types just doubles that duplication effort. 除了它只是感觉丑陋之外,我还想为X数量的签名参数专门化Method类,这已经涉及很多代码重复(希望Boost.Preprocessor可以在这里帮助),然后为void返回类型添加一个特化只需将复制工作加倍。
Is there anyway to avoid this second specialization for void return types? 反正有没有为void返回类型避免第二次专门化?
You could use Return
and just specialize operator()
handling. 您可以使用
Return
并专门执行operator()
处理。 No need to duplicate the whole template. 无需复制整个模板。
// I think it's a shame if c++0x really gets rid of std::identity. It's soo useful!
template<typename> struct t2t { };
// 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 call(t2t<Return>()); }
private:
Value call(t2t<void>) { return Value(); }
template<typename T>
Value call(t2t<T>) { return Value((m_Host->*m_Method)()); }
private:
Host * m_Host;
MethodType m_Method;
};
No, there is absolutely no way to pass a void
. 不,绝对没有办法通过
void
。 It is an irregularity in the language. 这是语言的不规范。
The function argument list (void)
is translated as ()
. 函数参数列表
(void)
被翻译为()
。 Bjarne prefers the latter to the former, and begrudgingly allowed the C convention as a very limited kind of syntactic sugar. Bjarne更喜欢后者和前者,并且不情愿地允许C约定作为一种非常有限的句法糖。 You can't even substitute a typedef alias of
void
, and you certainly can't have any other arguments. 你甚至不能替换
void
的typedef别名,你肯定不能有任何其他参数。
I personally think this is a bad idea. 我个人认为这是一个坏主意。 If you can write
void(expr)
, then you should be able to "initialize" an anonymous argument of type void
. 如果你可以编写
void(expr)
,那么你应该能够“初始化”一个void
类型的匿名参数。 If you could also write a function with an arbitrary number of void
arguments, there would be a way to execute a number of expressions in unspecified order, which would express concurrency in a way. 如果你也可以编写一个具有任意数量的
void
参数的函数,那么就有办法以未指定的顺序执行许多表达式,这将以某种方式表达并发性。
As for handling different-sized argument lists (also known as variadic), see variadic templates in C++0x before you start trying to learn Boost Preprocessor. 至于处理不同大小的参数列表(也称为可变参数),在开始尝试学习Boost预处理器之前,请参阅C ++ 0x中的可变参数模板。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.