在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 ++桥的模板函数。这个想法是通过一个自动推送或转换Lua堆栈的重载函数interpretValue
来桥接Lua和C ++函数。对于具有直接内置Lua表示的简单类型,使用代码(如示例B)很容易。
对于更复杂的类型,我还写了template <typename T> struct Data
来处理对象的内存管理(在Lua的GC和C ++端引用之间桥接),我希望能够重载interpretValue
以便它可以自动将userdata指针包装到Data<T>
中。我尝试使用以下内容,但是clang给了一个&#34;函数调用是不明确的&#34;错误:
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);
}
谢谢!
答案 0 :(得分:2)
好吧,你可以编写一个函数:
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);