[英]Replicate Haskell's Return Type Overloading (via Typeclasses) in C++
在Haskell中,類型類使您可以根據返回類型優雅地重載函數。 使用模板(示例A)在參數和返回類型都被重載的情況下,用C ++復制此代碼很簡單:
template <typename In, typename Out> Out f(In value);
template <typename T> int f<T, int>(T value) {
...
}
對應於Haskell的:
class F a b where
f :: a -> b
您甚至可以只重載大多數函數的返回類型(示例B):
template <typename Out> Out f(SomeClass const &value);
template <> inline int f(SomeClass const &value) {
return value.asInt();
}
template <> inline float f(SomClass const &value) {
return value.asFloat();
}
對應於以下內容:
class F a where
f :: SomeData -> a
但是我想做的是修改最后一個示例,以重載高階類型,即C ++中的模板結構。 也就是說,我希望能夠編寫類似於以下Haskell的專業化知識:
data Foo a = Foo a
instance F (Foo a) where
f someData = Foo $ ...
如何使用這種功能編寫模板(甚至有可能)?
作為參考,我打算用它來編寫Lua / C ++橋的模板函數。 這個想法是通過讓重載的函數interpretValue
自動從Lua棧中推送或轉換,在Lua和C ++函數之間架起橋梁。 對於具有直接內置Lua表示的簡單類型,使用示例B這樣的代碼就足夠容易了。
對於更復雜的類型,我還編寫了一個template <typename T> struct Data
來處理對象的內存管理(在Lua的GC和C ++側引用計數之間架橋),我希望能夠重載interpretValue
以便它可以自動將用戶Data<T>
指針包裝到Data<T>
。 我嘗試使用以下命令,但clang給出了“函數調用不明確”錯誤:
template <typename U> inline U &interpretValue(lua_State *state, int index) {
return Data<U>::storedValueFromLuaStack(state, index);
}
template <typename U> inline Data<U> interpretValue(lua_State *state, int index) {
return Data<U>::fromLuaStack(state, index);
}
謝謝!
好吧,您可以編寫一個函數:
template <class U>
interpretValueReturnType<U> interpretValue(lua_State *state, int index)
{
return interpretValueReturnType<U>(state, index);
}
然后,您需要使用強制轉換運算符編寫此返回類型,因此,您將獲得所需的內容:
template <class U>
class interpretValueReturnType
{
public:
interpretValueReturnType(lua_State *state, int index) : state(state), index(index) {}
operator U& () &&
{
return Data<U>::storedValueFromLuaStack(state, index);
}
operator Data<U> () &&
{
return Data<U>::fromLuaStack(state, index);
}
private:
lua_State *state;
int index;
};
見ideone :
int main() {
lua_State *state;
int& a = interpretValue<int>(state, 1);
Data<int> b = interpretValue<int>(state, 1);
}
在operator
聲明末尾的這個有趣的&&
是為了使該函數的結果難以存儲並在以后使用它-如此處:
auto c = interpretValue<float>(state, 1);
float& d = c; // not compile
需要使用std::move
因為&&
表示該函數只能用於右值引用:
auto c = interpretValue<float>(state, 1);
float& d = std::move(c);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.