[英]void return value from a function used as input to a templated function is seen as a parameter
假設您有一些目標類,其中包含一些方法:
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返回類型避免第二次專門化?
您可以使用Return
並專門執行operator()
處理。 無需復制整個模板。
// 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;
};
不,絕對沒有辦法通過void
。 這是語言的不規范。
函數參數列表(void)
被翻譯為()
。 Bjarne更喜歡后者和前者,並且不情願地允許C約定作為一種非常有限的句法糖。 你甚至不能替換void
的typedef別名,你肯定不能有任何其他參數。
我個人認為這是一個壞主意。 如果你可以編寫void(expr)
,那么你應該能夠“初始化”一個void
類型的匿名參數。 如果你也可以編寫一個具有任意數量的void
參數的函數,那么就有辦法以未指定的順序執行許多表達式,這將以某種方式表達並發性。
至於處理不同大小的參數列表(也稱為可變參數),在開始嘗試學習Boost預處理器之前,請參閱C ++ 0x中的可變參數模板。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.