【问题标题】:Member by member assignment of different classes based on the same template基于同一模板的不同类的逐个成员分配
【发布时间】:2021-12-28 12:01:11
【问题描述】:

假设一个类有两个不同的类,但它们的目的有些“等价”,所以它们有相同的成员,一个可以被另一个分配:

struct Pure
{
    QString name;
    int age = 18;
};

struct Observable
{
    QProperty<QString> name;
    QProperty<int> age {18};
    void operator=(const Pure& other)
    {
        name = other.name;
        age = other.age;
    }
};

QProperty 是一个template class from Qt,但我认为这个问题与 Qt 无关,因为它适用于与 T 进行转换/分配的任何其他 template &lt;typename T&gt; class Foo

问题是如何避免重复,所以不能轻易地从一个类中添加或删除成员而忘记在另一个类中执行此操作,同时仍然保留将一个类的对象分配给另一个类的可能性。

我用模板尝试了几件事,这似乎是最有希望的:

// Adding two helpers only available in C++ 20 for convenience.
template<typename T>
struct type_identity { using type = T; };    
template<typename T>
using type_identity_t = typename type_identity<T>::type;

template<template<typename T> typename T>
struct State
{
    T<QString> name;
    T<int> age;

//    std::enable_if_t<std::is_same<QProperty<class X>, T>>
//    operator=(const State<type_identity_t>& other)
//    {
//        name = other.name;
//        age = other.age;
//    }
};

int main()
{
    State<type_identity_t> state;
    state.age = 42;
    State<QProperty> observableState;
    observableState = state; // Desired use. Fails to compile without operator=
}

注释掉的代码无法编译(错误:使用模板模板参数'T'需要模板参数),错误在第一条注释行末尾的T,但我不知道如何解决这个问题。

【问题讨论】:

  • C++ 不能解决所有问题。以某种结构化格式(如 XML 或 YAML)在单独的文件中列出所有类成员及其类型,并编写一个简单的脚本来为这两个类生成 C++ 代码。将其集成到您的构建系统中。
  • 我知道这是一种可能。我经常使用代码生成,因为它在 Qt 中很常见,或者当您需要 IPC/RPC 等时。但是,您认为使用模板是不可能的吗?
  • 第一步半自动进行(目前还没有检查):Pure 可以静态检查 Observable 是否定义了两个成员。 Observable 在赋值运算符中间接检查它。
  • C++ 的当前状态不允许这样的东西完全在 C++ 本身中实现。
  • 谢谢,我知道基于元类提案的解决方案将节省所有样板文件。但我只是决定在operator= 上拥有一个模板和only 的副本。

标签: c++ templates sfinae


【解决方案1】:

您不能使用std::is_same&lt;QProperty&lt;class X&gt;, T&gt;,因为它试图将T 作为第二个参数传递给is_same,但它是一个模板,而is_same 需要一个类型。

您可以创建一个类似于is_same 的特征,它采用模板类来代替:

template<template<typename...> class A, template<typename...> class B>
struct is_same_template_class : std::false_type {};

template<template<typename...> class T>
struct is_same_template_class<T, T> : std::true_type {};

// use `is_same_template_class<T, QProperty>`

目前,似乎没有理由限制您的 operator= 可以做什么。为什么不这样:

template<template<typename> class T>
struct State
{
    T<QString> name;
    T<int> age;

    template<template<typename> class U>
    State& operator=(const State<U>& other)
    {
        name = other.name;
        age = other.age;
        return *this;
    }
};

我对 QT 不熟悉,但如果你重构一些逻辑,using Observable = QProperty&lt;Pure&gt;; 似乎也可以工作。

【讨论】:

  • 很好的回应,TVM!事实上,不限制operator= 可能是最好的选择。我太专注于只在需要时提供它。我不太习惯写模板。我知道 is_same 的参数是错误的,但我认为我可以通过添加更多模板/类型名关键字来表达我想要的。再次感谢。
  • 哦,QProperty&lt;T&gt; 确实可以在此处与 Pure 这样的复制构造/可分配类型一起使用,但是您可以订阅正在更改的整个复合类型。我想知道是否有可能更细化,逐个成员。现在我能。 :)
猜你喜欢
  • 2012-04-28
  • 2020-04-13
  • 2020-10-10
  • 1970-01-01
  • 1970-01-01
  • 2020-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多