gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 16:04:50 25 4
gpt4 key购买 nike

请注意,我在 C++03 中工作,C++11 的 deleted 函数对我不可用。

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

假设我有两个主要对象:一个核心库对象 Root 和一个派生的特殊情况下测试对象 Branch。我正在尝试开发一个测试夹具类 Fixture 来处理设置和与核心 Root 对象对话的细节。所以这是我到目前为止所构建内容的简化说明:

(Here is an ideone link 与下面的代码相同,除了我定义了自己的 noncopyable)

#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 时,编译器仍会考虑这些 private 声明:

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.

最佳答案

您的歧义在于 *this 可以同时绑定(bind)到 Root &Fixture &,并且两种转换都同样好(即派生到基础的转换)。

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

template <typename T> Fixture(T &)

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

但是,这太天真了,因为您实际上并不希望您的 Fixture 可以从任何东西构造。相反,您希望它只能从派生自 Root 的内容构造。我们可以使用一些 SFINAE 魔法来禁用无关的构造函数。首先是 C++11 版本:

#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++03 中隐式声明的复制构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17239204/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com