加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-16 03:08:54 所属栏目:百科 来源:网络整理
导读:请注意,我正在C 03工作,C11的已删除功能不可用. 我试图设计一个不可复制的对象,并阻止编译器考虑该类上隐式声明的复制构造函数.这是我正在开发的单元测试夹具. 考虑到我有两个主要对象:核心库对象,Root和派生的特殊对象被测试,Branch.我正试图开发一个测试
请注意,我正在C 03工作,C11的已删除功能不可用.

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

考虑到我有两个主要对象:核心库对象,Root和派生的特殊对象被测试,Branch.我正试图开发一个测试夹具类,Fixture处理细节的设置&与核心Root对象交谈.所以这是我迄今为止所建立的简单说明:

(Here is an ideone link与以下相同的代码,除了我已经定义了我自己的非复制)

#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 Fixture
{
public:
    Branch()
    :
        Fixture (*this)
    {
    }
};

int main()
{
    Branch branch;
}

编译结果如下:

main.cpp: In constructor ‘Branch::Branch()’:
main.cpp:30:23: error: call of overloaded ‘Fixture(Branch&)’ is ambiguous
main.cpp:30:23: note: candidates are:
main.cpp:13:5: note: Fixture::Fixture(Root&)
main.cpp:8:7: note: Fixture::Fixture(const Fixture&)

为了防止C 03编译器隐含地声明Fixture的复制构造函数是不可能的,除非我自己声明至少一个.但即使是:

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

…在Branch的初始化列表中初始化Fixture时,编译器仍然会考虑这些私有声明:

Fixture (*this)

我希望编译器根本不考虑这些复制构造函数.

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

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

…但我宁愿不是,因为它有点臭我的鼻子,非复制能力是我要通过派生Fixture从boost :: noncopyable的语义.

有没有办法阻止编译器在这种情况下考虑隐式声明的复制构造函数,而无需更改调用站点处的代码:

Fixture (*this)

>“不可能…”:标准C 03:12.8 / 4“特殊成员功能”:

If the class definition does not explicitly declare a copy
constructor,one is declared implicitly.

解决方法

你的含糊之处在于*这可以绑定到一个Root&和Fixture&,这两个转换同样好(即派生到基础转换).

诀窍是创建一个更好的匹配的重载.例如,

template <typename T> Fixture(T &)

将完全匹配任何左值,因此比需要转换的重载更好匹配.

然而,这太天真了,因为你实际上并不想让你的Fixture从任何东西都可以构建出来.相反,你希望它只能从根源派生的东西来构建.我们可以通过一些SFINAE魔法来禁用无关的构造函数.首先是C11版本:

#include <type_traits>

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

在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是从Root派生的.这个模板化构造函数与T = Branch的重载是一个完全匹配,比复制构造函数更好,所以它被明确地选择为最好的重载.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读