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

前端之家收集整理的这篇文章主要介绍了防止编译器在C 03中考虑隐式声明的复制构造函数前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
请注意,我正在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的重载是一个完全匹配,比复制构造函数更好,所以它被明确地选择为最好的重载.

猜你在找的C&C++相关文章