簡體   English   中英

在C ++中復制Haskell的返回類型重載(通過Typeclasses)

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM