【问题标题】:Custom Container emplace with variadic templates带有可变参数模板的自定义容器 emplace
【发布时间】:2015-02-20 12:00:17
【问题描述】:

我正在实现一个简单的圆形矢量类。我想实现一个 emplace 成员函数,但我收到一个我不明白的错误。对于我做错的事情,这可能是一个简单的修复,但由于我对可变参数模板没有太多经验,所以我无法弄清楚是什么......

我得到的错误是:

main.cpp: In function 'int main()':

main.cpp:104:50: error: no matching function for call to 'CircularVector<Item>::emplace(int, int, int, int, int, int, std::vector<int>, int)'
     v.emplace(1, 0, 1, 0, 1, 0, vector<int>(), -1);
                                                  ^

main.cpp:104:50: note: candidate is:

main.cpp:20:7: note: void CircularVector<T, Args>::emplace(const Args& ...) [with T = Item; Args = {}]
  void emplace(const Args &... args) {
       ^

main.cpp:20:7: note:   candidate expects 0 arguments, 8 provided

产生这个错误的源代码是(也位于这里http://coliru.stacked-crooked.com/a/37d50d6f23363357):

#include <vector>

using namespace std;

#define CIRCULAR_BUFFER_DEFAULT_SIZE 5000

template <typename T, typename ...Args>
class CircularVector {
public:
    CircularVector(int size) {
        _size = size;
        _v.reserve(_size);
    }

    CircularVector() {
        _size = CIRCULAR_BUFFER_DEFAULT_SIZE;
        _v.reserve(_size);
    }

    void emplace(const Args &... args) {
        ++Count;
        ++_indexWrite;
        if (_indexWrite > _size - 1) _indexWrite = 0;
        _v.emplace(_indexWrite, args...);
    }

    void push(const T& item) {
        ++Count;
        ++_indexWrite;
        if (_indexWrite > _size - 1) _indexWrite = 0;
        _v[_indexWrite] = item;
    }

    void pop(T& item) {
        item = _v[_indexRead];
        ++_indexRead;
        if (_indexRead > _size - 1) _indexRead = 0;
        --Count;
    }

    T& back() {
        return _v[(_indexRead + Count - 1) % _size];
    }


    void erase(int numItems) {
        _indexRead += numItems;
        if (_indexRead > _size - 1) _indexRead -= _size;
        Count -= numItems;
    }

    void eraseAt(int index) {
        swap(_v[index], _v[(_indexRead + Count - 1) % _size]);
        --Count;
        --_indexWrite;
        if (_indexWrite < 0) {
            _indexWrite = _size - 1;
        }
    }

    void clear() {
        _indexRead = 0;
        _indexWrite = -1;
        Count = 0;
    }


    T& operator[](std::size_t idx) {
        int index = _indexRead + idx;
        if (index > _size) index = index % _size;
        return _v[index];
    };

    int Count = 0;

private:
    int _indexWrite = -1;
    int _indexRead = 0;
    int _size = 0;

    std::vector<T> _v;
};


class Item {
public:
    double A;
    int B;
    int C;
    vector<int> D;
    int E;

    Item(double a, int b, int c, vector<int> &d, int e) {
        A = a;
        B = b;
        C = c;
        D = d;
        E = e;
    }
};

int main() {
    CircularVector<Item> v;
    v.emplace(1, 0, 1, 0, 1, 0, vector<int>(), -1);
}

【问题讨论】:

    标签: c++ variadic-templates emplace


    【解决方案1】:

    如果有人偶然发现同样的问题,我就是这样实现的:

    void emplace(Args&&... args) {
        ++Count;
        ++_indexWrite;
        if (_indexWrite > _size - 1) _indexWrite = 0;
        _v.emplace(_v.begin() + _indexWrite, std::forward<Args>(args)...);
    }
    

    虽然我真正想要的是使用该索引中的保留内存构造一个元素,而不是在该特定位置插入新元素。

    【讨论】:

      【解决方案2】:

      Args 必须是emplace 的模板参数,而不是CircularVector

      template <typename T>
      class CircularVector {
      public:
      
          /* ... */
      
          template<typename ...Args>
          void emplace(const Args &... args) {
              /* ... */
          }
      };
      

      另外,您应该考虑使用 emplace 的转发引用。

      【讨论】:

      • 我已经改了,但还是报错...coliru.stacked-crooked.com/a/b4be468fe999bc56
      • @BlunT std::vectoremplace() 将迭代器作为其第一个参数,而不是索引。无论如何,它会插入一个新元素,这可能不是您真正想要的。您可能应该只构造一个 T 并将其分配给索引处的元素。
      • 你说的是这样的话:coliru.stacked-crooked.com/a/457e31c0bc86ff25 吗?我仍然收到一些我认为与 ...args 相关的错误,我不太明白问题出在哪里。另外,我想避免内存被复制,我希望使用已经分配给向量的内存来构建元素......我并不是要滥用,但我不是真的得到我在这里想念的东西......
      猜你喜欢
      • 2014-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-20
      • 2015-12-14
      • 2015-05-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多