考虑这个旨在收集字符串序列的小类:
class issues_t final
{
private:
std::vector<std::string> m_issues;
public:
constexpr void operator()(std::string&& txt)
{
m_issues.push_back( std::move(txt) );
}
};
我计划将其用作:
issues_t issues;
do_something(issues);
这有效:
void do_something(issues_t& notify_issue)
{
notify_issue("something");
}
但我宁愿把它当作:
using fnotify_t = std::function<void(std::string&&)>;
void do_something(fnotify_t const& notify_issue)
{
notify_issue("something");
}
这可以编译但不起作用:在调试器中push_back()
执行但下划线向量未填充(godbolt),所以我在这里缺少什么?
最小可重现示例:
#include <string>
#include <vector>
#include <functional>
#include <print>
class issues_t final
{
private:
std::vector<std::string> m_issues;
public:
constexpr void operator()(std::string&& txt)
{
m_issues.push_back( std::move(txt) );
}
[[nodiscard]] constexpr auto begin() const noexcept { return m_issues.cbegin(); }
[[nodiscard]] constexpr auto end() const noexcept { return m_issues.cend(); }
};
using fnotify_t = std::function<void(std::string&&)>;
void do_first(fnotify_t const& notify_issue)
{
notify_issue("do_first");
}
void do_second(issues_t& notify_issue)
{
notify_issue("do_second");
}
int main()
{
issues_t issues;
issues("main");
do_first(issues);
do_second(issues);
for( const auto& issue : issues )
{
std::print(" {}\n", issue);
}
}
do_something
接受const&
可以绑定到临时对象的 a 。调用时,会构造do_something
一个临时对象,并且字符串存储在它包含的临时对象中,而不是原始的 中。std::function
"something"
issues_t
issues_t issues
您的设计很容易出现此类错误,而使用模板和 lambda 可能更方便:
更惯用的说法
do_something
应该是这样的:这些“改进”(1、2、3)中的任何一项都不是绝对必要的,但更惯用。