专门化可变模板的返回类型

Specializing return type for a variadic template

本文关键字:返回类型 专门化      更新时间:2023-10-16

首先,如果我犯了很大的英语错误,我很抱歉,我是法国人,但我正在尽我所能写得最好!好吧,我正在努力与c++ 11可变模板。我想做点小技巧

实际上,我想对模板的返回类型进行专门化,因为我知道它是一个可变模板。

我的目标是实现如下:

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

专门化对应于用户想要的返回类型。这是一个Lua绑定,所以如果用户没有精确指定返回类型,我就无法确定返回类型(显然,如果没有特化,默认值将是void return)。是在Lua中调用的函数的名称。然后,这3个整数对应于我的可变模板。

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

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

但是我似乎不能对模板函数进行部分特化。有人能帮我吗?

非常感谢!

非常感谢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);
}

这真的很简单,但我不知道到底该怎么做…谢谢大家!:)

不需要更改接口的解决方案是将函数调用转发到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)... )
}

,我们在DoCallFun中实现callFun的主体。如果需要访问LuaScript中的私有变量,我们将DoCallFun改为friend

现在,一个更好的解决方案可能是对大部分return类型依赖的行为使用"性状class"。如果您需要基于return类型调用不同的函数,而不是为每个略有不同的return类型编写一次相同的callFun,您可以创建一个"traits class",其中您基于return类型隔离差异。

如果类型为int,则需要调用int CallAndReturnInt(...);如果类型为double,则需要调用double CallAndReturnDouble(...)。而不是有两个主体的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) );
  }
};

和其他类似的方法,您的方法应该根据return类型而有所不同。

完美地转发对helper类成员函数的初始调用应该可以方便您实现所需的功能。

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上继续获得答案,不要忘记标记答案:)

为什么不特化函数模板?