可变参数模板的专用返回类型

时间:2013-05-31 15:39:18

标签: c++ templates c++11 specialization variadic

首先,如果我犯了很大的英语错误,我很抱歉,我是法国人,但我正尽力尽力写作!好吧,我正在努力使用C ++ 11可变参数模板。我想做一些有点棘手的事情。

确实,我想专门化我的模板的返回类型,知道它是一个可变参数模板。

我的目标是实现以下目标:

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

专门化对应于用户想要的返回类型。它是一个Lua绑定,所以如果用户不精确它,我无法确定返回类型(显然,默认情况下,如果没有特化,则返回void)。稍后,是Lua中调用的函数的名称。然后,3个整数对应于我的可变参数模板。

现在,我的模板看起来像这样:

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

但似乎我无法对模板功能进行部分专业化。有没有人可以帮助我?

非常感谢!

3 个答案:

答案 0 :(得分:1)

完美转发对辅助类成员函数的初始调用应该有助于你想要的东西。

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)    

如果您想了解更多关于您可以/不能使用它的信息,下面的链接可能会帮助您进行部分模板专业化。此外,如果您希望将来在StackOverflow继续获得答案,请不要忘记标记答案:)

Why Not Specialize Function Templates?

答案 1 :(得分:1)

帮助和文档非常感谢pheedbaq,但最后,我找到了一个非常简单的解决方案。我没有这样做,所以我会试着用这种操作符重载方式来感谢你;)

我所做的是打包可变参数,并调用另一个模板来专门处理返回类型。所以我有类似的东西:

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

这真的很简单,但看不清楚该怎么做...感谢大家! :)

答案 2 :(得分:1)

不需要更改界面的解决方案是将函数调用转发到template<> class,您可以专注于您的内容:

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

我们在callFun内实施DoCallFun的正文。如果需要访问LuaScript中的私有变量,我们会DoCallFunfriend

现在,更好的解决方案可能是使用“traits class”来处理大部分return类型依赖行为。如果您需要根据return类型调用其他函数,而不是为每个callFun类型编写一次相同的return,只会略有不同,您可以创建“traits {{ 1}}“您根据class类型隔离差异。

如果类型为return,则需要调用int CallAndReturnInt(...);如果类型为int,则需要调用double CallAndReturnDouble(...)。不要有两个double的主体,而是写一个特征类:

callFun

以及基于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) ); } }; 类型,您的方法应有所不同的其他方式的类似技巧。