Domanda

First, I'm sorry if I make big english mistakes, I'm french but I'm trying to write as best as I can! Well, I'm struggling with C++11 variadic template. I want to do something a little tricky.

Indeed, I want to specialize the return type of my template, knowing that it is a variadic template.

My goal is to achieve something like:

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

The specialization corresponds to the return type that the user want. It is a Lua binding, so I can't determine the return type if the user doesn't precise it (obviously, the default, if no specialization, would be void return). Later, is the name of the function that is called in Lua. Then, the 3 integers corresponds to my variadic template.

Right now, my template is looking like this :

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

But it appears that I cannot make a partial specialization of a template function. Is there anybody that could help me ?

Thank you very much!

È stato utile?

Soluzione

Help and documentation very much appreciated pheedbaq, but finally, I came with a really simple solution. I didn't tought of it that way, so I'll experiment with this way of operator overloading thanks to you ;)

What I've done is packing the variadic arguments, and calling another template to specialize on the return type. So I have something like that:

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

It was really quite simple, but couldn't see exactly how to do it... Thanks to everyone! :)

Altri suggerimenti

A solution that does not require changing your interface is to forward the function call to a template<> class, where you can specialize to your hearts content:

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)... )
}

and we implement the body of callFun within DoCallFun. If it needs access to private variables in LuaScript we make DoCallFun a friend.

Now, a better solution might be to use a "traits class" for much of the return-type dependent behavior. If you need to call a different function based on the return type, instead of writing the same callFun once for each return type with a slight difference, you can create a "traits class" where you isolate the difference based on return type.

Suppose you need to call int CallAndReturnInt(...) if the type is int and double CallAndReturnDouble(...) if the type is double. Instead of having two bodies of callFun, write a traits class:

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) );
  }
};

and similar techniques for other ways your method should differ based on the return type.

Perfect forwarding the initial call to a helper class member function should facilitate what you want.

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)    

The link below might help you with partial template specialization if you want to know more about what you can/can't do with it. Also, don't forget to mark an answer if you want to continue getting answers in the future here at StackOverflow :)

Why Not Specialize Function Templates?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top