Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 作为模板函数输入的函数的void返回值被视为参数_C++_Templates_Generic Programming - Fatal编程技术网

C++ 作为模板函数输入的函数的void返回值被视为参数

C++ 作为模板函数输入的函数的void返回值被视为参数,c++,templates,generic-programming,C++,Templates,Generic Programming,假设您有一些目标类,其中包含一些方法: class Subject { public: void voidReturn() { std::cout<<__FUNCTION__<<std::endl; } int intReturn() { std::cout<<__FUNCTION__<<std::endl; return 137; } }; 我在VC++2008中遇到以下错误: error C2664: 'Value::Value(

假设您有一些目标类,其中包含一些方法:

class Subject
{
public:
  void voidReturn() { std::cout<<__FUNCTION__<<std::endl; }
  int  intReturn()  { std::cout<<__FUNCTION__<<std::endl; return 137; }
};
我在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;
};
模板类方法;
//无参数签名的专门化
模板
类方法
{
公众:
typedef返回(主机::*MethodType)();
方法(Host*Host,MethodType方法):m_主机(Host),m_方法(Method){
值运算符(){返回值((m_主机->*m_方法)();}
私人:
主机*m_主机;
方法型m_法;
};
在返回某个内容(即intReturn)的方法上使用此Method类将如下所示:

Method< Subject, int () > intMeth( &subject, &Subject::intReturn );
Value intValue = intMeth();
MethodintMeth(&Subject,&Subject::intReturn);
Value intValue=intMeth();
但是,使用voidReturn方法执行此操作:

Method< Subject, void () > voidMeth( &subject, &Subject::voidReturn );
Value voidValue = voidMeth();
MethodvoidMeth(&Subject,&Subject::voidReturn);
值voidValue=voidMeth();
产生与上述类似的错误

一种解决方案是进一步对无效返回类型的方法进行部分专门化:

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;
};
模板
类方法
{
公众:
typedef无效返回;
typedef返回(主机::*MethodType)();
方法(Host*Host,MethodType方法):m_主机(Host),m_方法(Method){
值运算符(){return(m_Host->*m_Method)(),Value();}
私人:
主机*m_主机;
方法型m_法;
};
除了感觉很难看之外,我还想专门化X个签名参数的方法类,这已经涉及到大量的代码复制(希望Boost.Preprocessor可以在这里提供帮助),然后为void返回类型添加专门化只会使复制工作量加倍


是否有任何方法可以避免对void返回类型进行第二次专门化?

否,绝对没有办法传递
void
。这是语言上的不规范

函数参数列表
(void)
被翻译为
()
。与前者相比,比亚恩更喜欢后者,并且勉强允许C约定作为一种非常有限的语法糖类。您甚至不能将typedef别名替换为
void
,当然也不能有任何其他参数

我个人认为这是个坏主意。如果您可以编写
void(expr)
,那么您应该能够“初始化”类型为
void
的匿名参数。如果您还可以编写一个具有任意数量的
void
参数的函数,那么有一种方法可以按未指定的顺序执行大量表达式,这将以某种方式表示并发性


至于处理不同大小的参数列表(也称为变量列表),在开始学习Boost预处理器之前,请参阅C++0x中的变量模板。

您可以使用
返回
并专门化
操作符()
处理。不需要复制整个模板

// 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;
};
//如果c++0x真的摆脱了std::identity,我认为这是一种耻辱。太有用了!
模板结构t2t{};
//无参数签名的专门化
模板
类方法
{
公众:
typedef返回(主机::*MethodType)();
方法(Host*Host,MethodType方法):m_主机(Host),m_方法(Method){
值运算符(){return call(t2t());}
私人:
值调用(t2t){返回值();}
模板
值调用(t2t){返回值((m_主机->*m_方法)();}
私人:
主机*m_主机;
方法型m_法;
};

谢谢,我很害怕。我想我在boost.function中看到了一些类似的东西,但显然不是。感谢关于变量模板的提示,不幸的是,我还没有升级我的编译器。“带有一个void类型参数的函数参数列表被调整为没有参数的列表。”->实际上它更严格。在C99中,是这样的,但是在C++中,替换是纯句法的:令牌序列(“空”)表示零参数列表。但例如“(空)”中“空虚”表示空隙类型在C++ + 1中是非法的。我认为,这是一个写得非常好的问题……取消
标识的原因是定义它的
操作符()
使用右值引用而不是
常量&
会破坏太多已安装的代码!是的,那就是我要找的!我记得不久前读过Alexandrescu写的关于Type2Type的文章,但后来就忘了。
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;
};
// 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;
};