我有一个文本编辑器列表,每当用户选择文件时就会在应用程序上呈现该列表。它工作得很好,但是当我开始删除列表中的元素以表示它们已被用户关闭并且不会再次呈现时,当我选择之前删除的相同文件以具有重复项时,问题就开始出现。因此,我尝试先对列表进行排序,然后在渲染之前使用 std::unique 来删除重复项。
这是我渲染文本编辑器的部分
if(!Opened_TextEditors.empty())
{
std::sort(Opened_TextEditors.begin(), Opened_TextEditors.end());
auto last = std::unique(Opened_TextEditors.begin(), Opened_TextEditors.end());
Opened_TextEditors.erase(last, Opened_TextEditors.end());
auto it = Opened_TextEditors.begin();
while(it != Opened_TextEditors.end())
{
if(it->IsWindowVisible())
{
it->Render();
if(it->IsWindowFocused()){
char buffer[255];
selected_window_path = it->GetPath(); // determines which window is active or currently selected. For writing contents on status bar
selected_editor_path = it->GetPath(); // This is to deterimine which window is focused or currently selected. For determining where to render the next selected window. This is to reduce reordering during rendering.
auto cpos = it->GetCursorPosition();
snprintf(buffer, sizeof(buffer), "Ln %d, Col %-6d %6d lines | %s | %s | %s | %s ", cpos.mLine + 1, cpos.mColumn + 1, it->GetTotalLines(),
it->IsOverwrite() ? "Ovr" : "Ins",
it->CanUndo() ? "*" : " ",
it->GetFileExtension().c_str(),
it->GetFileName().c_str()
);
current_editor = std::string(buffer);
}
++it;
}
else {//Bug: When the editor was deleted and is selected again to be rendered, causes some sort of anomalies where it tends not being docked and somtimes when it was rendered and tried to close any window, every window will be deleted.
it = Opened_TextEditors.erase(it);
}
}
}
这是我添加所选文本编辑器的部分
auto it = std::find(Opened_TextEditors.begin(), Opened_TextEditors.end(), parentNode.FullPath);
if(it == Opened_TextEditors.end())
{
static unsigned int id = 0;
ArmSimPro::TextEditor editor(parentNode.FullPath, id,bg_col.GetCol());
auto programming_lang = ArmSimPro::TextEditor::LanguageDefinition::CPlusPlus();
++id;
for (int i = 0; i < sizeof(ppnames) / sizeof(ppnames[0]); ++i)
std::future<void> PreprocIdentifier = std::async(std::launch::async, SetupPreprocIdentifiers, programming_lang, ppvalues[i]);
for (int i = 0; i < sizeof(identifiers) / sizeof(identifiers[0]); ++i)
std::future<void> Identifiers = std::async(std::launch::async, SetupIdentifiers, programming_lang, identifiers[i], idecls[i]);
editor.SetLanguageDefinition(programming_lang);
std::ifstream t(parentNode.FullPath.c_str());
if (t.good())
{
std::string str;
t.seekg(0, std::ios::end);
str.reserve(t.tellg());
t.seekg(0, std::ios::beg);
str.assign((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
editor.SetText(str);
}
if(!selected_editor_path.empty()){
int index = GetTextEditorIndex(selected_editor_path) + 1;
Opened_TextEditors.insert(Opened_TextEditors.begin() + index, editor);
}
if(Opened_TextEditors.empty())
Opened_TextEditors.push_back(editor);
}
当我运行它时,它给出了一条错误消息:
call to object of class type 'std::less<void>': no matching call operator found
call to object of class type 'std::less<void>': no matching call operator found
因此,我在类上添加了一个重载“==”运算符的函数:
class TextEditor
{
public:
.....
bool operator==(TextEditor& other) { return this->path == other.path; }
bool operator==(const TextEditor& other) { return this->path == other.path; }
bool operator==(const std::string& full_path) const { return this->path == full_path; }
.....
};
我在
<algorithm>
方面没有太多经验,因为我刚刚开始学习几个月,但我怀疑错误来自于std::unique
。我发现this类似的问题,但仍然遇到相同的错误。我可以在 TextEditor
类上添加任何内容来满足 std::unique
上的参数吗?
在这个问题上,我看到人们说使用
std::set
来避免重复。但是,要允许在当前选定的文本编辑器旁边添加文本编辑器,需要能够在特定索引处插入。这是通过搜索列表并找到具有指定文件路径的编辑器然后获取其位置来完成的。
错误很可能来自
std::sort
而不是 std::unique
。 2-参数 std::sort
要求类型可以与 <
进行比较,而 TextEditor
不具备。
我会使用允许使用谓词的 3 参数
std::sort
,而不必向 operator <
类提供重载的 TextEditor
。
这是一个完整的示例:
#include <vector>
#include <iostream>
#include <algorithm>
class TextEditor
{
std::string path;
public:
TextEditor(const char * p) : path(p) {}
const std::string& getPath() const { return path;}
};
int main()
{
std::vector<TextEditor> v;
v.push_back("path1");
v.push_back("path2");
v.push_back("path1"); // Duplicate
std::sort(v.begin(), v.end(), [](const TextEditor& e1, const TextEditor& e2)
{ return e1.getPath() < e2.getPath(); });
auto it = std::unique(v.begin(), v.end(), [](const TextEditor& e1, const TextEditor& e2)
{ return e1.getPath() == e2.getPath(); });
v.erase(it, v.end());
for (auto& te : v)
{
std::cout << te.getPath() << "\n";
}
}
输出:
path1
path2
请注意,进行了 3 参数
std::unique
调用,因此不需要编写重载的 operator==
。