有没有办法在 C++ 中模仿 Kotlin 的数据类“copy()”?
这允许复制对象并在单个表达式中修改其特定部分,请参阅 Kotlin 示例:
data class SomeData(val a: Int, val b: String)
...
SomeData(a = 10, b = "10").copy(b = "ten")
在 C++20 中我可以做
struct SomeData {
int a;
string b;
};
...
SomeData sd1 = { .a = 10, .b = "10" };
SomeData sd2 = { .a = sd1.a, .b = "ten" };
但是当结构变得越来越大时,这会变得非常笨重和不安全。
我正在考虑编写自己的函数,该函数将充当复制构造函数,但也需要
std::initializer_list
在复制的对象上应用指定的初始化。
我以为这最终会不那么笨重,但最终我不太确定。无论如何,至少这是一种强调“指定您想要更改的成员”语义的替代方案,而不是一个具有“指定您想要保留和更改的成员”语义的列表。
您可以利用可变参数自动非类型模板参数,并将指向成员的指针作为参数,来指定您想要替换修改副本中的哪些成员及其新值:
namespace detail {
// Helper trait to get underlying type of member from pointer-to-member.
template <typename T> struct ptr_to_member_underlying;
template <typename ClassType, typename MemberType>
struct ptr_to_member_underlying<MemberType ClassType::*> {
using type = MemberType;
};
template <typename T>
using ptr_to_member_underlying_t = typename ptr_to_member_underlying<T>::type;
template <typename T, auto mem_ref, typename V>
void assignMember(T &t, V &&mem_value) {
t.*mem_ref = std::forward<V>(mem_value);
}
} // namespace detail
/// @tparam mem_refs Pointer-to-members for the public data members of
/// `t`that should be modified in the copy.
/// @param new_mem_values New values for these modified data members.
template <auto... mem_refs, typename T>
T modifiedCopy(T const &t,
detail::ptr_to_member_underlying_t<decltype(mem_refs)>
&&... new_mem_values) {
auto tc = t;
(detail::assignMember<T, mem_refs>(
tc, std::forward<detail::ptr_to_member_underlying_t<decltype(mem_refs)>>(
new_mem_values)),
...);
return tc;
}
int main() {
SomeData sd1{.a = 10, .b = "10"};
auto sd2 = modifiedCopy<&SomeData::b>(sd1, "ten");
}
您可以使用宏来简化此操作,但需要考虑使用宏的普遍问题。