创建可相互转换的模板类系列 [英] Create a family of template classes convertible to each other

查看:93
本文介绍了创建可相互转换的模板类系列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个模板类家族,其中的每个模板类都将从共同的基础派生。这个共同的基础将定义如何将这些派生类之一的实例转换为任何其他实例。我已经使用复制构造函数和复制赋值运算符创建了基类模板,这是代码:

I want to create a family of template classes, where each of them would derive from common base. This common base would define, how to convert instance of one of these derived classes to any other. I have created base class template with both copy constructor and copy assignment operator, here is the code:

template < class T >
struct class_family
{
    T data;
    class_family() = default;
    class_family(const class_family& a) : data(a.data) { }
    class_family& operator=(const class_family& a) { data = a.data; return *this; };
};

然后,我创建了2个派生类,它们从该基类派生,因此我可以避免对于派生类的每种可能组合,用于复制构造和复制分配的重复代码:

Then, I created 2 derived classes, which derive from this base class, so that I can avoid to duplicate code for copy construction and copy assignment for each possible combination of derived classes:

template < class T >
struct class_1
    : public class_family< T >
{
    using class_family< T >::class_family;
    using class_family< T >::operator=;
};

template < class T >
struct class_2
    : public class_family< T >
{
    using class_family< T >::class_family;
    using class_family< T >::operator=;
};

这是我的测试代码:

int main(int argc, char** argv)
{
    class_1<int> c1;
    class_2<int> c2;
    c1 = c2;
    // class_2<int> c3 = c1;
}

在进行复制分配时,一切都按预期进行,但是当我取消注释时我尝试使用类型为 class_1 的对象初始化类型为 class_2 的新对象的行,编译器抱怨以下错误:

When it comes to copy assignment, everything works as intended, however when I uncomment line where I try to initialize new object of type class_2 with object of type class_1, compiler complains with following error:

E0312   no suitable user-defined conversion from "class_1<int>" to "class_2<int>" exists

编译器看不到基类的继承副本构造函数吗?有什么解决方法可以避免为属于 class_family 的每个单个类复制副本构造函数?

Shouldn't compiler see inherited copy constructor from base class? Is there some workaround to avoid duplicating copy constructor for every single class belonging to class_family?

推荐答案

更短的繁殖:

struct B { };
struct D : B { using B::B; };
struct E : B { using B::B; };

E e{D{}}; // error

基本上,复制和移动构造函数从不继承-专门排除在候选对象之外。如果需要,您必须明确添加这些额外的候选人。

Basically, copy and move constructors are never inherited - those are specifically excluded from consideration as candidates. You'd have to explicitly add those extra candidates if you want them.

来自 [ over.match.funcs] / 8


从类类型 C继承的构造函数([class.inhctor.init]),其第一个参数类型为对 cv1 P 的引用如果参数列表中只有一个,则构造 cv2 D 类型的对象时,将从候选函数集中排除在模板实例化的构造函数中)参数和 C P P 相关与 D 有关。 [示例:

A constructor inherited from class type C ([class.inhctor.init]) that has a first parameter of type "reference to cv1 P" (including such a constructor instantiated from a template) is excluded from the set of candidate functions when constructing an object of type cv2 D if the argument list has exactly one argument and C is reference-related to P and P is reference-related to D. [ Example:

struct A {
  A();
  A(A &&);                              // #1
  template<typename T> A(T &&);         // #2
};
struct B : A {
  using A::A;
  B(const B &);                         // #3
  B(B &&) = default;                    // #4, implicitly deleted

  struct X { X(X &&) = delete; } x;
};
extern B b1;
B b2 = static_cast<B&&>(b1);            // calls #3: #1, #2, and #4 are not viable
struct C { operator B&&(); };
B b3 = C();                             // calls #3

结束示例]






这是 CWG 2356 以及 CWG 1959 P0136 )。

这篇关于创建可相互转换的模板类系列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆