2014-03-07 57 views
3

試圖獲取兩個回調的簽名並生成使用其每個返回值的回調簽名。組合模板參數以形成函數簽名時無效的void參數

鑑於回調AB =>生成F

實施例1)A:int(char) B:double(bool) => F:雙(INT)

實施例2)A:void(char) B:void(int) =>˚F :空隙(空隙)

void實例化一個回調作爲參數時跑進一個奇怪編譯器錯誤:

error: invalid parameter type ‘void’

有問題的代碼

template<class Signature> 
struct my_func; 

template<class Ret, class... Args> 
struct my_func<Ret(Args...)> 
{}; 

template<class FuncA, class FuncB> 
struct my_fwd; 

template<class ORet, class... OArgs, 
     class Ret, class... Args> 
struct my_fwd< 
    my_func<ORet(OArgs...)>, 
    my_func<Ret(Args...)> 
    > 
{ 
    my_func< ORet(Ret) > func; // <--- error 
}; 

int main(int, char *[]) 
{ 
    my_func<void(int)> my3; // (1) 
    my_func<void(void)> my4; // (2) 
    my_func<void()> my5;  // (3) 

    my_fwd< decltype(my3), my_func<void(char)> > fwd1; // (4) 
    my_fwd< decltype(my3), decltype(my4) > fwd2;  // (5) 

    return 0; 
} 

雖然有與my_func實例化沒有問題的有void(1), (2), (3),將my_fwd(4) (5)失敗,我想知道爲什麼。

解決方法?

我已經找到了解決方法,通過專業my_fwdRet == void

// with this specialization i can avoid the error 
template<class ORet, class... OArgs, 
     class... Args> 
struct my_fwd< 
    my_func<ORet(OArgs...)>, 
    my_func<void(Args...)> 
    > 
{ 
    my_func< ORet() > func; 
}; 

問題

什麼是編譯器試圖內

my_fwd< my_func<void(int)>, my_func<void(char)> >實例之間的區別:

- >my_func<void(void)> func

手冊版本在main():my_func<void(void)> my4

void專業正確解決方法?備擇方案?我顯然對專業化和代碼重複不感興趣。

回答

4

void作爲模板參數和手動編寫void (void) instatiating之間的區別是,後者則製造功能採取void參數。列表(void)作爲函數的參數是一個句法結構,其含義與()相同。這是來自C的遺留問題,其中()表示「參數未指定」,(void)表示「無參數」。 C++刪除了未指定的情況,並且()在那裏表示「無參數」。

但是,模板實例化在語法處理後很久才發生,所以實際嘗試實例化函數的參數(T)T = void會導致錯誤。正如嘗試聲明功能爲(std::remove_reference<decltype(std::declval<void*>())>::type)(即void實際上拼寫爲一種類型)。

恐怕你能解決這個問題的唯一方法確實是專門爲void