如果具有相同模式的模板化ctor,如何删除自动生成的副本ctor

时间:2015-10-14 18:37:42

标签: templates visual-studio-2012 visual-c++ constructor

我遇到了自动生成的复制文件的问题。我知道即使我有一个具有相同模式的ctor,也会生成一个,因为我的ctor是模板化的,因此不是复制文件。所以我认为A和B的表现如预期的那样(第二个问题1:A和B是否真的应该阴险地产生一个伪造的复制品?)。无论如何,当我制作我的ctor的副本时,sans const(C),自动生成的副本ctor不会被调用。这是我对我的问题的修复,但它闻起来很糟糕(第2章:为什么const会产生差异?编译器是否应该能够将const提升为使用我的ctor?)。我更喜欢(D)超过(C),但即使演员看起来正确,自动生成的复制ctor也会被调用(第3章:为什么我的演员会失败?)。我不想添加一个虚拟参数(E)只是为了能够调用正确的ctor(2ndary4:为什么演员在这里工作?)。

我觉得我应该能够删除自动生成的复制文件(F& G),但我无法弄清楚如何。所以我的问题是。当你有一个具有相同模式的模板化ctor时,如何删除自动生成的复制文件?

// This example calls the auto generated copy ctor
template <int X> class A {
    int m_n;
public:
    A(int n) : m_n(n) { }
    template <int X1> A(const A<X1>& r) :  m_n(10) { }
};

// This example calls the auto generated copy ctor
template <int X> class B {
    int m_n;
public:
    B(int n) : m_n(n) { }
    template <int X1> B(const B<X1>& r, int n=10) : m_n(n) { }
};

// This example calls my ctor
template <int X> class C {
    int m_n;
public:
    C(int n) : m_n(n) { }
    template <int X1> C(const C<X1>& r) : m_n(10) { }
    template <int X1> C(C<X1>& r) : m_n(10) { }
};

// This example calls the auto generated copy ctor
template <int X> class D {
    int m_n;
public:
    D(int n) : m_n(n) { }
    template <int X1> D(const D<X1>& r) : m_n(10) { }
    template <int X1> D(D<X1>& r) : D(const_cast<const D<X1>&>(r)) { }
};

// This example calls ctor
template <int X> class E {
    int m_n;
public:
    E(int n) : m_n(n) { }
    template <int X1> E(const E<X1>& r, int n=10) : m_n(n) { }
    template <int X1> E(E<X1>& r) : E(r, 10) { }
};

// This example fails to compile
template <int X> class F {
    int m_n;
public:
    F(int n) : m_n(n) { }
    template <int X1> F(const F<X1>& r) : m_n(10) { }
    F<X>(F<X>& r) = delete;
};

// This example fails to compile
template <int X> class G {
    int m_n;
public:
    G(int n) : m_n(n) { }
    template <int X1> G(const G<X1>& r) : m_n(10) { }
    template <int X1> G(G<X1>& r) = delete;
};

int main(int argc, char* argv[])
{
    A<1> a1(1);  // m_n = 1
    A<1> a2(a1); // !FAIL! m_n = 1, NOT 10

    B<1> b1(1);  // m_n = 1
    B<1> b2(b1); // !FAIL! m_n = 1, NOT 10

    C<1> c1(1);  // m_n = 1
    C<1> c2(c1); // m_n = 10

    D<1> d1(1);  // m_n = 1
    D<1> d2(d1); // !FAIL! m_n = 1, NOT 10

    E<1> e1(1);  // m_n = 1
    E<1> e2(e1); // m_n = 10

    F<1> f1(1);  // m_n = 1
    //F<1> f2(f1); // wont compile, referencing deleted function

    G<1> g1(1);  // m_n = 1
    //G<1> g2(g1); // wont compile, referencing deleted function
}

1 个答案:

答案 0 :(得分:1)

您不应该删除复制构造函数,而应该定义它。如果你想避免代码重复,有两种方法(遗憾的是你不能直接在C ++中为模板化构造函数设置模板参数):

  1. 您可以使用模板化构造函数的功能创建模板化类方法,并在两个构造函数中调用它。这种方式不够好,因为你不能在这种方法中使用初始化列表。
  2. 您可以使用辅助构造函数的参数间接设置模板参数。但是这种技术需要C ++ 11委托构造函数支持,不幸的是VS 2012缺少它(你可以使用Visual C ++ 2012 November CTP作为临时解决方案)。
  3. 请参阅下面的代码示例:

    template <class T>
    struct Identity{};
    
    template <class T>
    struct S
    {
        S() = default;
    
        template <class U>
        S(const S<U>&, Identity<U> = {})
        {
            std::cout << "Templated constructor" << std::endl;
        }
    
        S(const S<T>& s) : S(s, Identity<T>{})
        {
            std::cout << "Copy constructor" << std::endl;
        }
    };
    
    // ...
    
    S<int> s1;
    S<int> s2(s1);
    

    Live demo