【问题标题】:Variadic template recursion, incorrect number of arguments可变模板递归,参数数量不正确
【发布时间】:2017-07-23 18:41:47
【问题描述】:

我目前正在使用 C/C++ MATLAB API,并且正在尝试使用可变参数模板函数;我对它不是很熟悉。它将有效地将数据结构列表输出到 MATLAB 结构中。

编译时我收到以下 2 个错误:

matLink::output2': 找不到匹配的重载函数

'void matLink::output2(mxArray *, int, const char**, const currentData &, const restData&...)': 需要 5 个参数 - 提供 3 个

template<typename... Data>
void matLink::output(const char* file, const char* varName, const char** label, const Data&... data) {

    mxArray * pStruct;

    // do some stuff...

    output2(pStruct, 0, label, data...); // start recursion

    // some more
}

template<typename currentData, typename... restData>
void matLink::output2(mxArray* pStruct, int index, const char** label, const currentData& current, const restData&... rest) {
    matWrite(pStruct, current, label[index], index);
    output2(pStruct, ++index, label, rest...); // both errors at this line
}

template<typename lastData>
void matLink::output2(mxArray* pStruct, int index, const char** label, const lastData& last) {
    // base case
    output2(pStruct, last, label[index], index);
}

我该如何解决这个问题?

【问题讨论】:

  • 交换output2 定义的顺序。以错字结尾。
  • 交换 output2 函数只会导致相同的错误集,但第二个错误是“...需要 4 个参数 - 提供了 3 个”?
  • 我早就预料到会出现错误 - 4 参数调用似乎是模棱两可的。在这样的调用中,没有理由更喜欢第二个重载而不是第一个。此外,您的第二个重载调用 output2 的方式与任一签名都不匹配 - 应该调用哪个重载?

标签: c++ templates variadic-templates


【解决方案1】:

看看这样的事情是否有帮助:

template<typename... Data>
struct OutputHelper {
  static void output(mxArray* pStruct, int index, const char** label, const Data& ...) {
    // Do nothing. We'll only get here when `Data` is empty
  }
};

template<typename First, typename... Rest>
struct OutputHelper<First, Rest...> {
  static void output(mxArray* pStruct, int index, const char** label,
                     const First& first, const Rest& rest...) {
    matWrite(pStruct, first, label[index], index);
    OutputHelper<Rest...>::output(pStruct, index+1, label, rest...);
  }
};

template<typename... Data>
void matLink::output(const char* file, const char* varName, const char** label,
                     const Data&... data) {
   mxArray * pStruct;
   OutputHelper<Data...>::output(pStruct, 0, label, data...); // start recursion
}

与函数模板不同,类模板支持部分特化。因此,通过类模板路由递归很方便 - 当部分特化可用时,更容易制定特殊情况。

【讨论】:

    【解决方案2】:

    实际上,经过仔细检查,应该可以使用更简单的方法:

    template<typename... Data>
    void matLink::output(const char* file, const char* varName, const char** label,
                         const Data&... data) {
        mxArray * pStruct;
        int index = 0;
        auto dummy = {(matWrite(pStruct, data, label[index], index), index++)...};
    }
    

    Demo

    这利用了以下事实:a) 参数包上的表达式可以在初始化器列表中展开,b) 此类列表中的各个初始化器保证按从左到右的顺序执行。

    【讨论】:

      猜你喜欢
      • 2017-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-18
      • 2017-03-05
      相关资源
      最近更新 更多