简体   繁体   中英

Template function specialization with a templated argument

I have a generic function for pushing stuff on to the lua stack called luaU_push, which must be specialized for any type that wants to use it. For example:

template <>
inline void luaU_push<>(lua_State* L, const Vector2i& val)
{
    lua_newtable(L);
    luaU_setfield<int>(L, -1, "x", val.x);
    luaU_setfield<int>(L, -1, "y", val.y);
}

It turns out that Vector2i is actually a typedef. The real type is Vector2<int> . In a few other places I use Vector2f s, which are just a typedef for Vector2<float> .

I'd like to be able to have a luaU_push for Vector2f s. I could make a duplicate function for Vector2f, but I'd prefer to make this one generic so I can use it on any kind of Vector2<T> , but I can't figure out the syntax to do that. I thought that I could do something like this, but this does not appear to work:

template <>
template <typename T>
inline void luaU_push<>(lua_State* L, const sf::Vector2<T>& val)
{
    lua_newtable(L);
    luaU_setfield<T>(L, -1, "x", val.x);
    luaU_setfield<T>(L, -1, "y", val.y);
}

Is there a way to get this working the way I want?

Edit:

Follow up question: I had intended to use the answer to this question to fix a set of functions, including a few that only differ by return type, but I don't think the answer given is sufficient for this. For example, I have this function (which is basically the opposite of the function above)

template <>
inline sf::Vector2i luaU_to<>(lua_State* L, int index)
{
    return sf::Vector2i(
        luaU_getfield<int>(L, index, "x"),
        luaU_getfield<int>(L, index, "y"));
}

I don't believe that there's a way to use overloading to make this work in a generic way, and I can't use partial specialization. Is there any way to make it work in this case?

Take this answer as a COMMENT.

template < typename T >
inline void luaU_push(lua_State* L, const sf::Vector2<T>& val)
{
    lua_newtable(L);
    luaU_setfield<T>(L, -1, "x", val.x);
    luaU_setfield<T>(L, -1, "y", val.y);
}

This should work. And in case of templated functions, a "base template" function will always have higher priority than a fully specialized one.

EDIT ::

You have overloaded the function "luaU_to" based upon the return type ! Which is not allowed and possible (unless you use some un-understandable/untidy nasty trick)

What you can do is, create a specialized version for each return data type and dont let compiler do the argument deduction for ie mention the data type explicitly in the template call.

For your follow-up question:

as ArunMu noted above, it's illegal to overload a function or to specialize a template on the return type only.

What you could do instead is something like this:

class LuaCheck {
public:
  LuaCheck (lua_State* L, int index)
    : L_(L), index_ (index)
  { }

  operator int ()    { return luaL_checkinteger(L_, index_); } // (a)
  operator double () { return luaL_checknumber(L_, index_); }  // (b)

private:
  lua_State* L_;
  int        index_;
};

int main () {
  lua_State * L = ...;
  int index = ...;

  int    a = LuaCheck (L, index);  // will call (a)
  double b = LuaCheck (L, index);  // will call (b)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM