gpt4 book ai didi

c++ - 是否有一种非重复的方式允许程序员在成员初始化的复制和 move 语义之间进行选择?

转载 作者:搜寻专家 更新时间:2023-10-31 02:23:04 26 4
gpt4 key购买 nike

我希望能够使用 move semantics 初始化类的每个字段或复制语义。构造函数都将使用基本相同的代码进行构造,如下所示:

LogRecord::LogRecord(const Logger &logger, LogLevel level, const std::wstring &message)
: level(level), logger_name(logger.GetName()), message(message), sequence_number(LogRecord::record_count++), source_class_name(), source_method_name(), time(std::chrono::system_clock::now()) {
}
LogRecord::LogRecord(const Logger &logger, LogLevel level, std::wstring &&message)
: level(level), logger_name(logger.GetName()), message(message), sequence_number(LogRecord::record_count++), source_class_name(), source_method_name(), time(std::chrono::system_clock::now()) {
}
LogRecord::LogRecord(const Logger &logger, LogLevel level, const std::wstring &message, const std::wstring &source_class_name, const std::wstring &source_method_name)
: level(level), logger_name(logger.GetName()), message(message), sequence_number(LogRecord::record_count++), source_class_name(source_class_name), source_method_name(source_method_name), time(std::chrono::system_clock::now()) {
}
LogRecord::LogRecord(const Logger &logger, LogLevel level, std::wstring &&message, const std::wstring &source_class_name, const std::wstring &source_method_name)
: level(level), logger_name(logger.GetName()), message(message), sequence_number(LogRecord::record_count++), source_class_name(source_class_name), source_method_name(source_method_name), time(std::chrono::system_clock::now()) {
}
LogRecord::LogRecord(const Logger &logger, LogLevel level, const std::wstring &message, std::wstring &&source_class_name, const std::wstring &source_method_name)
: level(level), logger_name(logger.GetName()), message(message), sequence_number(LogRecord::record_count++), source_class_name(source_class_name), source_method_name(source_method_name), time(std::chrono::system_clock::now()) {
}
LogRecord::LogRecord(const Logger &logger, LogLevel level, std::wstring &&message, std::wstring &&source_class_name, const std::wstring &source_method_name)
: level(level), logger_name(logger.GetName()), message(message), sequence_number(LogRecord::record_count++), source_class_name(source_class_name), source_method_name(source_method_name), time(std::chrono::system_clock::now()) {
}

等等

有没有比像这样简单地为每个可能的组合声明一个构造函数更好的方法来解决这个问题?

class LogRecord {
public:
LogRecord(const Logger &logger, LogLevel level, const std::wstring &message);
LogRecord(const Logger &logger, LogLevel level, std::wstring &&message);
LogRecord(const Logger &logger, LogLevel level, const std::wstring &message, const std::wstring &source_class_name, const std::wstring &source_method_name);
LogRecord(const Logger &logger, LogLevel level, std::wstring &&message, const std::wstring &source_class_name, const std::wstring &source_method_name);
LogRecord(const Logger &logger, LogLevel level, const std::wstring &message, std::wstring &&source_class_name, const std::wstring &source_method_name);
LogRecord(const Logger &logger, LogLevel level, std::wstring &&message, std::wstring &&source_class_name, const std::wstring &source_method_name);
LogRecord(const Logger &logger, LogLevel level, const std::wstring &message, const std::wstring &source_class_name, std::wstring &&source_method_name);
LogRecord(const Logger &logger, LogLevel level, std::wstring &&message, const std::wstring &source_class_name, std::wstring &&source_method_name);
LogRecord(const Logger &logger, LogLevel level, const std::wstring &message, std::wstring &&source_class_name, std::wstring &&source_method_name);
LogRecord(const Logger &logger, LogLevel level, std::wstring &&message, std::wstring &&source_class_name, std::wstring &&source_method_name);
...
private:
std::wstring message, source_class_name, source_method_name;
...
};

这是一个简化的形式,使其更容易阅读。Object 是具有成员的类,Member 是成员的类型名。 Member 类型同时定义了复制构造函数和 move 构造函数。

基本上,我的问题是如何以更少的代码重复执行以下操作:

class Object {
public:
Object(const Member &x, const Member &y, const Member &z) : x(x), y(y), z(z) {}
Object(Member &&x, const Member &y, const Member &z) : x(x), y(y), z(z) {}
Object(const Member &x, Member &&y, const Member &z) : x(x), y(y), z(z) {}
Object(Member &&x, Member &&y, const Member &z) : x(x), y(y), z(z) {}
Object(const Member &x, const Member &y, Member &&z) : x(x), y(y), z(z) {}
Object(Member &&x, const Member &y, Member &&z) : x(x), y(y), z(z) {}
Object(const Member &x, Member &&y, Member &&z) : x(x), y(y), z(z) {}
Object(Member &&x, Member &&y, Member &&z) : x(x), y(y), z(z) {}
private:
Member x, y, z;
}

最佳答案

我不会为所有这些重载而烦恼。始终按值获取 std::wstring 参数,并在内存初始化程序中 std::move 它们。那么你只需要 3 个构造函数定义。需要注意的是,在向您传递右值的情况下,您会招致额外的 move 构造,但您很可能会接受它。

LogRecord(const Logger &logger, LogLevel level, std::wstring message)
: level(level), logger_name(logger.GetName()), message(std::move(message)), ...
{}

请注意,由于小字符串优化,对于较小的 n 值, move 构造实际上可能是 O(n)


另一种选择是评论中提到的完美转发。你可以做类似的事情

template<typename Message>
LogRecord(const Logger &logger, LogLevel level, Message&& message)
: level(level), logger_name(logger.GetName()), message(std::forward<Message>(message)), ...
{}

也许可以添加 static_assert 来打印更好的错误消息,Message 是或可转换为 std::wstring

关于c++ - 是否有一种非重复的方式允许程序员在成员初始化的复制和 move 语义之间进行选择?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29677121/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com