2016-01-18 34 views
0

我需要一個具有可變數量參數的模板函數。目前我的問題是通過使用幾個模板函數來解決的。但是現在我需要在我的類函數中做一個包裝方法,以及將這些代碼打包到一個函數中的其他原因。我需要一個具有可變數量參數的模板函數

static void sendData(SSL *ssl, Command com) 
{ 
    std::string comStr(COM_SIZE, ' '); 
    memcpy(&comStr[0], &com, COM_SIZE); 
    sslWrite(ssl, comStr); 
} 

template<class T> 
void sendData(SSL *ssl, Command com, const T &t) 
{ 
    std::string serialArg; 
    OByteStream obs(serialArg); 
    obs << t; 
    obs.flush(); 

    const int serialArgSize = serialArg.size(); 
    std::string comAndSerialData(COM_SIZE + serialArgSize, ' '); 
    memcpy(&comAndSerialData[0], &com, COM_SIZE); 
    memcpy(&comAndSerialData[COM_SIZE], &serialArg[0], serialArgSize); 

    sslWrite(ssl, comAndSerialData); 
} 

template<class T1, class T2> 
void sendData(SSL *ssl, Command com, const T1 &t1, const T2 &t2) 
{ 
    std::string serialArgs; 
    OByteStream obs(serialArgs); 
    obs << t1 << t2; 
    obs.flush(); 

    const int serialArgsSize = serialArgs.size(); 
    std::string comAndSerialData(COM_SIZE + serialArgsSize, ' '); 
    memcpy(&comAndSerialData[0], &com, COM_SIZE); 
    memcpy(&comAndSerialData[COM_SIZE], &serialArgs[0], serialArgsSize); 

    sslWrite(ssl, comAndSerialData); 
} 

template<class T1, class T2, class T3> 
void sendData(SSL *ssl, Command com, const T1 &t1, const T2 &t2, const T3 &t3) 
{ 
    std::string serialArgs; 
    OByteStream obs(serialArgs); 
    obs << t1 << t2 << t3; 
    obs.flush(); 

    const int serialArgsSize = serialArgs.size(); 
    std::string comAndSerialData(COM_SIZE + serialArgsSize, ' '); 
    memcpy(&comAndSerialData[0], &com, COM_SIZE); 
    memcpy(&comAndSerialData[COM_SIZE], &serialArgs[0], serialArgsSize); 

    sslWrite(ssl, comAndSerialData); 
} 

//... 

如何在一個函數中編寫該函數?


這是我嘗試使用可變參數模板

void flush(OByteStream &obs) 
{ 
    obs.flush(); 
} 

template<typename T, typename... Targs> 
void flush(OByteStream &obs, T value, Targs... Fargs) 
{ 
    obs << value; 
    flush(obs, Fargs); 
} 

template<typename... Targs> 
void sendData(SSL *ssl, Command com, Targs... Fargs) 
{ 
    std::string serialArgs; 
    OByteStream obs(serialArgs); 
    flush(obs, Fargs); 

    const int serialArgsSize = serialArgs.size(); 
    std::string comAndSerialData(COM_SIZE + serialArgsSize, ' '); 
    memcpy(&comAndSerialData[0], &com, COM_SIZE); 
    memcpy(&comAndSerialData[COM_SIZE], &serialArgs[0], serialArgsSize); 

    sslWrite(ssl, comAndSerialData); 
} 

flush(obs, Fargs); - 錯誤C3520: 'Fargs':參數包必須在這方面

+6

尚未[可變參數模板參數包(http://en.cppreference.com/w/cpp/language/parameter_pack)的幫你嗎? –

回答

1
inline void flush(OByteStream &obs) 
{ 
    obs.flush(); 
} 

template<typename T, typename... Targs> 
void flush(OByteStream &obs, T &value, Targs&... Fargs) 
{ 
    obs << value; 
    flush(obs, Fargs...); 
} 

template<typename... Targs> 
void sendData(SSL *ssl, Command com, Targs&... Fargs) 
{ 
    std::string serialArgs; 
    OByteStream obs(serialArgs); 
    flush(obs, Fargs...); 

    const int serialArgsSize = serialArgs.size(); 
    std::string comAndSerialData(COM_SIZE + serialArgsSize, ' '); 
    memcpy(&comAndSerialData[0], &com, COM_SIZE); 
    memcpy(&comAndSerialData[COM_SIZE], &serialArgs[0], serialArgsSize); 

    sslWrite(ssl, comAndSerialData); 
} 
+0

rvalues存在問題:無法將參數3從'bool'轉換爲'bool'' – Ufx

+0

但是,如果將Targs&Targs &&和T&更改爲T &&它可以工作。這是好的解決方案嗎? – Ufx

6
template<class...Ts> 
void sendData(SSL *ssl, Command com, const Ts&... ts) 

... 擴大將<<行更換爲:

for_each_arg([&](auto&&t){obs << t;},ts...); 

for_each_arg

template<class F,class...Ts> 
void for_each_arg(F&&f, Ts&&... ts){ 
    using discard=int[]; 
    (void)discard{ 0, ((
    f(std::forward<Ts>(ts)) 
),void(),0)...} 
} 

這是神祕而有效。

這會讓C++ 11變得更難,因爲您沒有auto&& lambdas。您可以改爲使用模板operator()來編寫手卷結構。

這並不代替零參數的情況下,自然,並給出你的代碼是多麼短,我不會扭曲自己到pretzils來處理它。


如何使用模板操作符()替換C++ 14自動lambda來編寫C++ 11函數對象?

假設你有一個C++ 14的λ,看起來像這樣:

auto f = [&](auto&& x) { /* some code */ }; 

與模板operator()把它變成一個C++ 11函數對象,首先確定你捕捉每個實際的事情,手動捕獲它們。假設/* code */使用名稱bobalice並隱式使用this。然後重寫這樣的行:

auto f = [&bob, &alice, this](auto&& x) { /* some code */ }; 

其中我們列出了我們捕獲的所有內容。

接下來,取/* some code */並使其每次使用this顯式。如果我們使用m_x,請將其替換爲this->m_x

下一步是計算出bobalicethis的類型。假設它們是BobAliceMyClass。創建一個類似如下的類:

struct function_object_f { 
    Bob const& bob; 
    Alice const& alice; 
    MyClass* self; 
}; 

用捕獲的變量按順序排列。現在添加template operator()

struct function_object_f { 
    Bob const& bob; 
    Alice const& alice; 
    MyClass* self; 
    template<class X> 
    void operator()(X&& x)const { 
    /* some code */ 
    } 
}; 

現在,隨着self取代this每一個明確提及在/* some code */

將這個類之前你的函數你在哪裏使用在lambda

改寫原線。

auto f = function_object_f{bob, alice, this}; 

,我們正在做。 (請注意,捕獲順序在這裏很重要:它必須匹配function_object_f成員變量聲明)。 f與lambda幾乎相同,但其類型有一個名稱。

(對於沒有捕獲的lambdas,它缺少隱式轉換函數指針,但這是另一天的樣板)。

+1

這不需要尾部參數是全部相同的類型,而在原始代碼中,1,2或3個參數可以是所有不同的類型? –

+0

@JonathanLeffler否:所有類型都通過'Ts'轉發到lambda。 – Quentin

+0

'void for_each_arg(F && f,Ts && ts){' - 錯誤C3520:'Ts':參數包必須在此上下文中擴展 – Ufx

0

您可以

template<typename... Targs> 
void flush(OByteStream &obs, Targs... Fargs) 
{ 
    using swallow = int[sizeof...(Targs)]; 
    (void) swallow{(obs << Fargs, 0)...}; 
} 

該技術避免了遞歸更換這兩個沖水功能。當然,你可以更換obs << Fargs與任何函數調用,您需要:

template<typename Callable, typename... Targs> 
void call_for_each(Callable&& callable, Targs... Fargs) 
{ 
    using swallow = int[sizeof...(Targs)]; 
    (void) swallow{(callable(Fargs), 0)...}; 
} 
相關問題