C++ 防止编译器考虑C+中隐式声明的复制构造函数+;03

C++ 防止编译器考虑C+中隐式声明的复制构造函数+;03,c++,C++,请注意,我使用的是C++03,C++11的deleted函数对我不可用 我试图设计一个不可复制的对象,并阻止编译器考虑该类上隐式声明的复制构造函数。这是我正在开发的单元测试夹具 假设我有两个主要对象:一个核心库对象,Root,一个派生的测试中的特殊情况对象,Branch。我正在尝试开发一个测试夹具类,fixture,它处理设置核心根对象并与之对话的细节。这是我到目前为止构建的一个简化示例: (与下面的代码相同,只是我定义了自己的noncopyable) 除非我自己至少声明了一个副本构造函数,否则

请注意,我使用的是C++03,C++11的
delete
d函数对我不可用

我试图设计一个不可复制的对象,并阻止编译器考虑该类上隐式声明的复制构造函数。这是我正在开发的单元测试夹具

假设我有两个主要对象:一个核心库对象,
Root
,一个派生的测试中的特殊情况对象,
Branch
。我正在尝试开发一个测试夹具类,
fixture
,它处理设置核心
对象并与之对话的细节。这是我到目前为止构建的一个简化示例:

(与下面的代码相同,只是我定义了自己的
noncopyable

除非我自己至少声明了一个副本构造函数,否则无法*阻止C++03编译器隐式声明
Fixture
的副本构造函数。但即使:

class Fixture
:
    public boost::noncopyable
{
public:
    Fixture (Root& root)
    :
        mRoot (root)
    {
    }
private:
    Fixture (const Fixture&);
    Fixture (Fixture&);
    Root& mRoot;
};
<> >编译器在“<代码>分支/<代码>初始化列表:

初始化<代码>夹具<代码>时仍要考虑这些代码>私下<代码> >声明
Fixture (*this)
< >我希望编译器不要简单地考虑这些复制构造函数。

我可以通过自己做一些扭曲来做到这一点:

Fixture (static_cast <Root&> (*this))
?


  • “不可能…”:标准C++03:12.8/4,“特殊成员函数”:
如果类定义没有显式声明副本 构造函数,则隐式声明一个


在C++98和C++11中都无法防止复制构造函数签名的存在
=delete
也不会从重载集中删除某些内容,只有在选中时才会失败

如果不想弄乱Fixture的公共接口,我没有比插入显式cast更好的主意


不影响接口的选项包括通过指针传递
,以区别于复制构造函数的引用,以及为了重载解析而传递标记。如果您想了解更多关于这些的信息,请留下评论。

如果您不打算将
分支
作为
Fixture
的实例传递,则根本不需要继承它。如果我没有弄错的话,您基本上希望能够在
Fixture
中为
Root
的所有实例设置一些东西。所以让我们来攻击这个原因,而不是弯曲C++。strong>免责声明:如果不是这样,恐怕我没有任何建议

对于这个问题,我将使
Branch
有一个
Fixture
的实例作为它的成员,并重载复制
Branch
的构造函数来创建
Fixture
的实例,方法是将自身作为实例传递给
Fixture
的构造函数,并将赋值操作符传递给
Fixture
实例。下面是一个简单的例子:

#include <boost/utility.hpp>
#include <boost/noncopyable.hpp>

class Root
{
};

class Fixture
:
    public boost::noncopyable
{
public:
    Fixture (Root& root)
    :
        mRoot (root)
    {
    }
private:
    Root& mRoot;
};

class Branch
:
    public Root
{
public:
    Branch()
    : mFixture(*this)
    {
    }

    Branch(const Branch& branch)
    : Root(*this)
    , mFixture(*this)
    /* other 'Branch' members to be copied */
    {
    }

    Branch& operator = (const Branch& branch)
    {
        Root::operator=(branch);
        /* copy other 'Branch' members, except 'mFixture' */
    }

    Fixture& getFixture()
    {
        return mFixture;
    }

    const Fixture& getFixture() const
    {
        return mFixture;
    }

private:
    Fixture mFixture;
};
#包括
#包括
类根
{
};
班级固定装置
:
公共增强::不可复制
{
公众:
固定装置(根部和根部)
:
mRoot(根)
{
}
私人:
根与根;
};
班支部
:
公共根
{
公众:
分支机构()
:mFixture(*此)
{
}
分公司(施工分公司和分公司)
:Root(*this)
,mFixture(*此)
/*要复制的其他“分支”成员*/
{
}
分支和运算符=(常量分支和分支)
{
根::运算符=(分支);
/*复制除“mFixture”之外的其他“分支”成员*/
}
Fixture&getFixture()
{
返回mFixture;
}
常量Fixture&getFixture()常量
{
返回mFixture;
}
私人:
夹具制造;
};

您的含糊不清之处在于,
*此
可以绑定到
根&
夹具&
,并且两种转换都同样好(即派生到基转换)

诀窍是创建一个更好匹配的重载。比如说,

template <typename T> Fixture(T &)
在C++03中,我们使用Boost,不能使用默认模板参数:

#include <boost/type_traits.hpp>

template <typename T>
Fixture(T & x,
        typename boost::enable_if<boost::is_base_of<Root, T> >::type * = NULL)
: mRoot(x)
{ }
#包括
模板
夹具(T&x、,
typename boost::enable_if::type*=NULL)
:mRoot(x)
{ }

现在可以保证
T
是从
Root
派生的。此模板化构造函数的重载与
T=Branch
完全匹配,优于复制构造函数,因此它被明确地选为最佳重载。

C++11中删除的函数会有帮助吗?被删除的函数仍然参与重载解析。@KerrekSB:老实说,我不知道。如果你认为他们参与解决方案是对的,那么我认为他们不会有帮助。我认为a应该毫无疑问地优先……@KerrekSB:Aha。您的示例使用C++11,但我可以使用它。Boost中有相应的特性…+1我可以传递指针,但我宁愿传递引用,因为我将存储引用。如果我改变ctor以获取指针,那么无论如何我都必须改变呼叫站点代码,因此我想我更喜欢这种情况下的
静态\u cast
。顺便说一句,我很乐意搞乱
Fixture
公共
界面,只要我不改变
分支
中的呼叫站点代码,对于
分支&
,此重载不再可行。也许
是可转换的
。我忍不住觉得SFINAE的魔力有点过火了。总之,使用一个简单的
模板
构造函数(非SFINAE),如果我传递一些不可转换的东西(比如
FooBar
),它无论如何都会编译失败。这显然不起作用,因为
是相同的
在这种情况下不会编译,正如我所说的,我使用的是C++03。我会解决它。@johndilling:如果你不想让构造函数污染你的类,你绝对需要SFINAE。重载解析并不关心主体是否会编译。您需要删除不需要的重载
#include <boost/utility.hpp>
#include <boost/noncopyable.hpp>

class Root
{
};

class Fixture
:
    public boost::noncopyable
{
public:
    Fixture (Root& root)
    :
        mRoot (root)
    {
    }
private:
    Root& mRoot;
};

class Branch
:
    public Root
{
public:
    Branch()
    : mFixture(*this)
    {
    }

    Branch(const Branch& branch)
    : Root(*this)
    , mFixture(*this)
    /* other 'Branch' members to be copied */
    {
    }

    Branch& operator = (const Branch& branch)
    {
        Root::operator=(branch);
        /* copy other 'Branch' members, except 'mFixture' */
    }

    Fixture& getFixture()
    {
        return mFixture;
    }

    const Fixture& getFixture() const
    {
        return mFixture;
    }

private:
    Fixture mFixture;
};
template <typename T> Fixture(T &)
#include <type_traits>

template <typename T,
          typename = typename std::enable_if<std::is_base_of<Root, T>::value>::type>
Fixture(T & x)
: mRoot(x)
{ }
#include <boost/type_traits.hpp>

template <typename T>
Fixture(T & x,
        typename boost::enable_if<boost::is_base_of<Root, T> >::type * = NULL)
: mRoot(x)
{ }