vector中特定位置的unique_ptr的向量
A vector of unique_ptr at specific positions in vector
我有一个名为 Grid 的 class,它由 Cell 组成。每个单元格都可以有自己的格式(概念类似于MSExcel)。
Grid 中的格式保存在一个 vector std::vector<std::unique_ptr<CellFormat>> m_CellFormatTable
中,它拥有所有格式,所以每当我需要读取 Cells 格式时,我都会从 vector 中读取它,只要有变化,它被报告回载体。抱歉,我对 C++11 标准很陌生,所以我的想法可能是错误的。
由于网格是矩阵,每个单元格属于矩阵的不同部分,当单元格格式发生变化时,它应该反映在矩阵的正确部分,即正确定位在向量中(细胞格式表)。因此,在这个阶段我不能使用向量的push_back
方法。
单元格格式class:
struct CellFormat
{
wxFont m_Font;
wxColor m_BackgroundColor, m_TextColor;
int m_HorizontalAlignment, m_VerticalAlignment;
CellFormat(Grid* ws) {
m_BackgroundColor = ws->GetDefaultCellBackgroundColour();
m_TextColor=ws->GetDefaultCellTextColour();
int horizontal = 0, vertical = 0;
ws->GetDefaultCellAlignment(&horizontal, &vertical);
}
CellFormat(const CellFormat& other) {
m_Font = other.m_Font;
m_BackgroundColor = other.m_BackgroundColor;
m_TextColor = other.m_TextColor;
m_HorizontalAlignment = other.m_HorizontalAlignment;
m_VerticalAlignment = other.m_VerticalAlignment;
}
CellFormat& operator=(const CellFormat& other) {
if (this == &other) return *this;
m_Font = other.m_Font;
m_BackgroundColor = other.m_BackgroundColor;
m_TextColor = other.m_TextColor;
m_HorizontalAlignment = other.m_HorizontalAlignment;
m_VerticalAlignment = other.m_VerticalAlignment;
return *this;
}
};
在Grid.h
class Grid{
std::vector<std::unique_ptr<CellFormat>> m_CellFormatTable;
//
CellFormat* GetCellFormat(int row, int column);
void SetCellFormat(int row, int column, CellFormat format);
void ApplyCellFormat(int row, int column, const CellFormat* format);
CellFormat* CreateCellFormat(int row, int column);
//rest is omitted
}
在Grid.cpp
Grid(some arguments){
m_CellFormatTable.resize(nrows*ncols);
//rest is omitted
}
CellFormat* Grid::GetCellFormat(int row, int column)
{
int ncols= GetNumberCols();
return m_CellFormatTable[row*ncols+ column].get();
}
void Grid::SetCellFormat(int row, int column, CellFormat other)
{
CellFormat* format = GetCellFormat(row, column);
if (format == 0) format = CreateCellFormat(row, column);
*format = other;
}
void Grid::ApplyCellFormat(int row, int column, const CellFormat * format)
{
if (format == 0) {
int ncols= GetNumberCols();
//Set everything to default values
//Omitted
m_CellFormatTable[row*ncols+ column].reset();
}
else {
wxColor bgcolor = format->m_BackgroundColor;
if (bgcolor.IsOk()) SetCellBackgroundColour(row, column, bgcolor);
SetCellTextColour(row, column, format->m_TextColor);
SetCellFont(row, column, format->m_Font);
SetCellAlignment(row, column, format->m_HorizontalAlignment, format->m_VerticalAlignment);
}
}
CellFormat* Grid::CreateCellFormat(int row, int column)
{
int ncols= GetNumberCols();
CellFormat* format = new CellFormat(this);
m_CellFormatTable.emplace(m_CellFormatTable.begin() + row*ncols+ column, std::move(format));
return format;
}
每当我格式化一个单元格时,假设它的背景颜色发生了变化,我都会使用以下尝试:
CellFormat* format = ws->GetCellFormat(row, col);
if (format == 0) format = ws->CreateCellFormat(row, col);
if (ChangeFillColor) {
ws->SetCellBackgroundColour(row, col, m_LastChosenFillColor);
format->m_BackgroundColor = m_LastChosenFillColor;
}
代码在 format->m_BackgroundColor
点的 ApplyCellFormat
函数失败,因为本应作为单元格背景颜色的颜色无效。这告诉我,最有可能 CreateCellFormat
没有将 CellFormat 放在正确的位置。我尝试使用 insert
而不是 emplace
但编译器 (VS 2015) 抱怨我的所有尝试。
任何想法表示赞赏。
你有几个问题。
一个是你添加了一个 CellFormat*
但你的矢量存储 unique_ptr
;所以你需要 std::make_unique
新格式。
问题:您确定需要指针向量而不是对象向量吗?
另一个是您假定向量具有所有单元格的所有数据,如果尚未设置,则为 0
。那是错误的。向量的元素数量与 'pushed' 或 'emplaced' 一样多。
假设您有 'pushed' 单元格 (0,0) 的格式。现在您想设置 (5,2) 的格式,即(假设您有 10 列)向量中的第 52 个元素,但您只有一个。所以 vector[51]
是未定义的(vector.at(51)
会引发错误)。
首先添加所有单元格格式,其中一些值 = 0 表示尚未设置。或者重新考虑您的策略。
顺便说一下,您可以使用 wxGridCellAttr 来提供您自己编写的代码。
根据您使用 unique_ptr
的 vector
(而不是对象)这一事实,我推断并非矩阵的所有元素实际上都被占用了。在这种情况下,最好使用 std::map
(或 std::unordered_map
,如果矩阵非常大)对象(而不是 unique_ptr
)。
template<typename T>
struct grid
{
using index = std::pair<unsigned, unsigned>;
// insert element if not already present
// returns if insertion occurred
template<typename...Args>
bool insert(index const&i, Args&&...args)
{
return data.emplace(std::forward<Args>(args)...).second;
}
// remove element (if it exists)
void remove(index const&i)
{
data.erase(i);
}
// get pointer to element, may be nullptr
T* get(index const&i)
{
auto it = data.find(i);
return it==data.end() ?
nullptr : std::addressof(*it);
}
private:
std::map<index,T> data;
};
我在这部分代码中看到您的代码失败的原因:
CellFormat* format = ws->GetCellFormat(row, col);
if (format == 0) format = ws->CreateCellFormat(row, col);
if (ChangeFillColor) {
ws->SetCellBackgroundColour(row, col, m_LastChosenFillColor);
format->m_BackgroundColor = m_LastChosenFillColor;
}
是因为你的class是如何定义的:
class Grid{
std::vector<std::unique_ptr<CellFormat>> m_CellFormatTable;
//
CellFormat* GetCellFormat(int row, int column);
void SetCellFormat(int row, int column, CellFormat format);
void ApplyCellFormat(int row, int column, const CellFormat* format);
CellFormat* CreateCellFormat(int row, int column);
//rest is omitted
}
默认情况下,您的 class 的成员和函数设置为 private:
将您的 class 更改为:
class Grid {
public:
typedef std::vector<std::unique_ptr<CellFormat>> Format;
private:
Format m_CellFormatTable;
public:
CellFormat* getCellFormat( int row, int column );
void setCellFormat( int row, int column, const CellFormat& format );
void applyCellFormat( int row, int column, const CellFormat& format );
// Add This Function If Needed
Format getCellFormatTable() const { return m_CellFormatTable; }
};
所以你的 class 的成员函数被声明为 public:
然后外部和非朋友对象现在可以访问这个 class 的成员函数并且能够return 通过 get 方法的数据结构。
感谢所有有用的评论和帖子。终于按预期运行了。
正如 Ripi2 所建议的,CellFormat
向量中的对象没有被初始化,所以在构造函数中我对它们进行了初始化。这里也没有介绍,我在代码的某个地方有一个未初始化的对象向量,所以也更正了那部分。
虽然遍历网格的所有行和列并创建默认格式并不是最好的主意,但我未来的工作将是 Walter 的建议,即使用集合。
Grid(some arguments){
for (int i = 0; i < nrows*ncols; i++) {
m_CellFormatTable.emplace_back(new CellFormat(this));
}
//Rest is omitted
}
还更正了以下代码:
CellFormat* Grid::CreateCellFormat(int row, int column)
{
int ncols = GetNumberCols();
CellFormat* format = new CellFormat(this);
std::unique_ptr<CellFormat> ptr(format);
m_CellFormatTable.emplace(m_CellFormatTable.begin() + row*ncols + column,std::move(ptr));
return format;
}
跟踪格式化的一种方法是:
CellFormat* format = ws->GetCellFormat(i, j);
if (ChangeFillColor) {
ws->SetCellBackgroundColour(i, j, m_LastChosenFillColor);
format->m_BackgroundColor = m_LastChosenFillColor;
}
我有一个名为 Grid 的 class,它由 Cell 组成。每个单元格都可以有自己的格式(概念类似于MSExcel)。
Grid 中的格式保存在一个 vector std::vector<std::unique_ptr<CellFormat>> m_CellFormatTable
中,它拥有所有格式,所以每当我需要读取 Cells 格式时,我都会从 vector 中读取它,只要有变化,它被报告回载体。抱歉,我对 C++11 标准很陌生,所以我的想法可能是错误的。
由于网格是矩阵,每个单元格属于矩阵的不同部分,当单元格格式发生变化时,它应该反映在矩阵的正确部分,即正确定位在向量中(细胞格式表)。因此,在这个阶段我不能使用向量的push_back
方法。
单元格格式class:
struct CellFormat
{
wxFont m_Font;
wxColor m_BackgroundColor, m_TextColor;
int m_HorizontalAlignment, m_VerticalAlignment;
CellFormat(Grid* ws) {
m_BackgroundColor = ws->GetDefaultCellBackgroundColour();
m_TextColor=ws->GetDefaultCellTextColour();
int horizontal = 0, vertical = 0;
ws->GetDefaultCellAlignment(&horizontal, &vertical);
}
CellFormat(const CellFormat& other) {
m_Font = other.m_Font;
m_BackgroundColor = other.m_BackgroundColor;
m_TextColor = other.m_TextColor;
m_HorizontalAlignment = other.m_HorizontalAlignment;
m_VerticalAlignment = other.m_VerticalAlignment;
}
CellFormat& operator=(const CellFormat& other) {
if (this == &other) return *this;
m_Font = other.m_Font;
m_BackgroundColor = other.m_BackgroundColor;
m_TextColor = other.m_TextColor;
m_HorizontalAlignment = other.m_HorizontalAlignment;
m_VerticalAlignment = other.m_VerticalAlignment;
return *this;
}
};
在Grid.h
class Grid{
std::vector<std::unique_ptr<CellFormat>> m_CellFormatTable;
//
CellFormat* GetCellFormat(int row, int column);
void SetCellFormat(int row, int column, CellFormat format);
void ApplyCellFormat(int row, int column, const CellFormat* format);
CellFormat* CreateCellFormat(int row, int column);
//rest is omitted
}
在Grid.cpp
Grid(some arguments){
m_CellFormatTable.resize(nrows*ncols);
//rest is omitted
}
CellFormat* Grid::GetCellFormat(int row, int column)
{
int ncols= GetNumberCols();
return m_CellFormatTable[row*ncols+ column].get();
}
void Grid::SetCellFormat(int row, int column, CellFormat other)
{
CellFormat* format = GetCellFormat(row, column);
if (format == 0) format = CreateCellFormat(row, column);
*format = other;
}
void Grid::ApplyCellFormat(int row, int column, const CellFormat * format)
{
if (format == 0) {
int ncols= GetNumberCols();
//Set everything to default values
//Omitted
m_CellFormatTable[row*ncols+ column].reset();
}
else {
wxColor bgcolor = format->m_BackgroundColor;
if (bgcolor.IsOk()) SetCellBackgroundColour(row, column, bgcolor);
SetCellTextColour(row, column, format->m_TextColor);
SetCellFont(row, column, format->m_Font);
SetCellAlignment(row, column, format->m_HorizontalAlignment, format->m_VerticalAlignment);
}
}
CellFormat* Grid::CreateCellFormat(int row, int column)
{
int ncols= GetNumberCols();
CellFormat* format = new CellFormat(this);
m_CellFormatTable.emplace(m_CellFormatTable.begin() + row*ncols+ column, std::move(format));
return format;
}
每当我格式化一个单元格时,假设它的背景颜色发生了变化,我都会使用以下尝试:
CellFormat* format = ws->GetCellFormat(row, col);
if (format == 0) format = ws->CreateCellFormat(row, col);
if (ChangeFillColor) {
ws->SetCellBackgroundColour(row, col, m_LastChosenFillColor);
format->m_BackgroundColor = m_LastChosenFillColor;
}
代码在 format->m_BackgroundColor
点的 ApplyCellFormat
函数失败,因为本应作为单元格背景颜色的颜色无效。这告诉我,最有可能 CreateCellFormat
没有将 CellFormat 放在正确的位置。我尝试使用 insert
而不是 emplace
但编译器 (VS 2015) 抱怨我的所有尝试。
任何想法表示赞赏。
你有几个问题。
一个是你添加了一个 CellFormat*
但你的矢量存储 unique_ptr
;所以你需要 std::make_unique
新格式。
问题:您确定需要指针向量而不是对象向量吗?
另一个是您假定向量具有所有单元格的所有数据,如果尚未设置,则为 0
。那是错误的。向量的元素数量与 'pushed' 或 'emplaced' 一样多。
假设您有 'pushed' 单元格 (0,0) 的格式。现在您想设置 (5,2) 的格式,即(假设您有 10 列)向量中的第 52 个元素,但您只有一个。所以 vector[51]
是未定义的(vector.at(51)
会引发错误)。
首先添加所有单元格格式,其中一些值 = 0 表示尚未设置。或者重新考虑您的策略。
顺便说一下,您可以使用 wxGridCellAttr 来提供您自己编写的代码。
根据您使用 unique_ptr
的 vector
(而不是对象)这一事实,我推断并非矩阵的所有元素实际上都被占用了。在这种情况下,最好使用 std::map
(或 std::unordered_map
,如果矩阵非常大)对象(而不是 unique_ptr
)。
template<typename T>
struct grid
{
using index = std::pair<unsigned, unsigned>;
// insert element if not already present
// returns if insertion occurred
template<typename...Args>
bool insert(index const&i, Args&&...args)
{
return data.emplace(std::forward<Args>(args)...).second;
}
// remove element (if it exists)
void remove(index const&i)
{
data.erase(i);
}
// get pointer to element, may be nullptr
T* get(index const&i)
{
auto it = data.find(i);
return it==data.end() ?
nullptr : std::addressof(*it);
}
private:
std::map<index,T> data;
};
我在这部分代码中看到您的代码失败的原因:
CellFormat* format = ws->GetCellFormat(row, col); if (format == 0) format = ws->CreateCellFormat(row, col); if (ChangeFillColor) { ws->SetCellBackgroundColour(row, col, m_LastChosenFillColor); format->m_BackgroundColor = m_LastChosenFillColor; }
是因为你的class是如何定义的:
class Grid{ std::vector<std::unique_ptr<CellFormat>> m_CellFormatTable; // CellFormat* GetCellFormat(int row, int column); void SetCellFormat(int row, int column, CellFormat format); void ApplyCellFormat(int row, int column, const CellFormat* format); CellFormat* CreateCellFormat(int row, int column); //rest is omitted }
默认情况下,您的 class 的成员和函数设置为 private:
将您的 class 更改为:
class Grid {
public:
typedef std::vector<std::unique_ptr<CellFormat>> Format;
private:
Format m_CellFormatTable;
public:
CellFormat* getCellFormat( int row, int column );
void setCellFormat( int row, int column, const CellFormat& format );
void applyCellFormat( int row, int column, const CellFormat& format );
// Add This Function If Needed
Format getCellFormatTable() const { return m_CellFormatTable; }
};
所以你的 class 的成员函数被声明为 public:
然后外部和非朋友对象现在可以访问这个 class 的成员函数并且能够return 通过 get 方法的数据结构。
感谢所有有用的评论和帖子。终于按预期运行了。
正如 Ripi2 所建议的,CellFormat
向量中的对象没有被初始化,所以在构造函数中我对它们进行了初始化。这里也没有介绍,我在代码的某个地方有一个未初始化的对象向量,所以也更正了那部分。
虽然遍历网格的所有行和列并创建默认格式并不是最好的主意,但我未来的工作将是 Walter 的建议,即使用集合。
Grid(some arguments){
for (int i = 0; i < nrows*ncols; i++) {
m_CellFormatTable.emplace_back(new CellFormat(this));
}
//Rest is omitted
}
还更正了以下代码:
CellFormat* Grid::CreateCellFormat(int row, int column)
{
int ncols = GetNumberCols();
CellFormat* format = new CellFormat(this);
std::unique_ptr<CellFormat> ptr(format);
m_CellFormatTable.emplace(m_CellFormatTable.begin() + row*ncols + column,std::move(ptr));
return format;
}
跟踪格式化的一种方法是:
CellFormat* format = ws->GetCellFormat(i, j);
if (ChangeFillColor) {
ws->SetCellBackgroundColour(i, j, m_LastChosenFillColor);
format->m_BackgroundColor = m_LastChosenFillColor;
}