2013-05-31 37 views
2

首先,如果我犯了大的英語錯誤,我很抱歉,我是法語的,但我正在努力盡我所能寫出最好的答案!好吧,我正在努力與C++ 11 variadic模板。我想做一些棘手的事情。專門針對可變模板的返回類型

事實上,我想專門化我的模板的返回類型,知道它是一個可變模板。

我的目標是要實現這樣的:

l.callFun<int>("addition", 40, 1, 1); 

專業化對應於用戶想要的返回類型。它是一個Lua綁定,所以如果用戶不精確,我不能確定返回類型(顯然,默認情況下,如果沒有專門化,將返回void)。稍後,是在Lua中調用的函數的名稱。然後,這3個整數對應於我的可變參數模板。

現在,我的模板看起來像這樣:

template <typename Z, typename T, typename... U> 
Z LuaScript::callFun(const std::string& name, const T& head, const U&... tail); 

但現在看來,我不能做一個模板函數的偏特。有沒有人能幫助我?

非常感謝!

+0

那麼你想寫的部分專業化是什麼?調用時可以部分指定模板參數,但這是另一回事。 –

+0

我想要專注的是返回類型! – Theo13

+0

我認爲你的意思是你想參數化返回類型;)。在我的回答中,我包含了一篇關於部分專業化的文章的鏈接,以防您想更多地瞭解它。 –

回答

1

幫助和文檔非常讚賞pheedbaq在未來得到答案在這裏,但最後,我想出了一個真正的解決方案簡單我沒有這樣做,所以我會試試這種運營商超載感謝你;)

我所做的是包裝可變參數,並調用另一個模板來專注於返回類型。所以我有這樣的事情:

template <typename Z, typename... T> 
Z LuaScript::callFun(const std::string& name, const T&... args) 
{ 
    Z ret; 
    callFunReal(args); 
    [...] 
    ret = returnType<Z>(); 
    return (ret); 
} 

這真的很簡單,但看不出如何做到這一點......感謝大家! :)

+0

很高興你明白了:)嘿,不要忘記標記答案,即使它是你自己的。這將建立聲譽,當人們決定回答問題時,人們會看到這一點。 –

+0

是的,我知道,這只是我必須等待一天來標記我自己的答案作爲答案,我只是等待:) – Theo13

+0

大聲笑,我明白了。爲了好玩,我修改了使用完美轉發的代碼,並允許用戶按照您最初描述的方式撥打電話。 –

1

將初始調用完美轉發給助手類成員函數應該可以幫助您實現。如果你想知道更多關於你可以/不可以用它做什麼

template<typename Z> 
struct callFun_helper { 
    template<typename T, typename... U> 
    static Z help(const std::string& name, const T& head, const U&... tail) { 
     Z thing; 
     //do something with "thing" 
     return thing; 
    } 
}; 

template<typename Z, typename S, typename T, typename... U> 
auto callFun(S&& s, T&& t, U&&... u) 
-> decltype(callFun_helper<Z>::help(std::forward<S>(s), std::forward<T>(t), std::forward<U>(u)...)) { 
    return callFun_helper<Z>::help(std::forward<S>(s), std::forward<T>(t), std::forward<U>(u)...); 
} 

//main 
callFun<string>("addition", 40, 1, 1)  

以下鏈接可以幫助您與局部模板專業化。另外,不要忘記標誌着一個答案,如果你想繼續在StackOverflow的:)

Why Not Specialize Function Templates?

1

,不需要改變你的界面是函數調用轉發給template<> class,在那裏你可以專注於你的心內容:A液

template<typename R, typename... Ts> 
struct DoCallFun { 
    R operator()(LuaScript* self, std::string const& name, Ts&&... ts) { 
    } 
}; 

template <typename Z, typename... T> 
Z LuaScript::callFun(const std::string& name, Ts&&... ts) { 
    return DoCallFun<Z, Ts...>()(this, name, head, std::forward<Ts>(ts)...) 
} 

並在我們實施的callFun身體DoCallFun。如果需要訪問LuaScript中的私有變量,我們製作DoCallFun a friend

現在,更好的解決方案可能是對return類型相關行爲的大部分使用「特徵class」。如果您需要根據return類型調用不同的功能,而不是爲每個return類型編寫一個相同的callFun,而略有不同,您可以創建一個「特徵class」,根據return類型區分差異。

假設你需要調用int CallAndReturnInt(...)如果類型爲intdouble CallAndReturnDouble(...)如果類型爲double。相反,具有callFun兩個機構的,寫一個traits類:其他方式

template<typename T> 
struct lua_return_traits; 
template<> 
struct lua_return_traits<int> { 
    template<typename... Ts> 
    static int call_and_return(Ts&&... ts) { 
    return CallAndReturnInt(std::forward<Ts>(ts)); 
    } 
}; 
template<> 
struct lua_return_traits<double> { 
    template<typename... Ts> 
    static double call_and_return(Ts&&... ts) { 
    return CallAndReturnDouble(std::forward<Ts>(ts)); 
    } 
}; 

和類似技術的方法應該區分基礎上,return類型。