- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
以下代码是如何工作的?
typedef char (&yes)[1];
typedef char (&no)[2];
template <typename B, typename D>
struct Host
{
operator B*() const;
operator D*();
};
template <typename B, typename D>
struct is_base_of
{
template <typename T>
static yes check(D*, T);
static no check(B*, int);
static const bool value = sizeof(check(Host<B,D>(), int())) == sizeof(yes);
};
//Test sample
class Base {};
class Derived : private Base {};
//Expression is true.
int test[is_base_of<Base,Derived>::value && !is_base_of<Derived,Base>::value];
请注意 B
是私有(private)基地。这是如何运作的?
请注意 operator B*()
是常量。为什么它很重要?
为什么是 template<typename T> static yes check(D*, T);
优于 static yes check(B*, int);
?
注意:它是boost::is_base_of
的精简版(宏被删除) .这适用于各种编译器。
最佳答案
让我们暂时假设 B
实际上是 D
的基数.然后调用check
, 这两个版本都是可行的,因为 Host
可以转换为D*
和 B*
.这是一个用户定义的转换序列,如 13.3.3.1.2
所述。来自 Host<B, D>
至D*
和 B*
分别。为了找到可以转换类的转换函数,为第一个check
合成了以下候选函数功能根据 13.3.1.5/1
D* (Host<B, D>&)
第一个转换函数不是候选函数,因为 B*
无法转换为 D*
.
对于第二个函数,存在以下候选:
B* (Host<B, D> const&)
D* (Host<B, D>&)
这是两个采用宿主对象的转换函数候选者。第一个通过 const 引用获取它,而第二个没有。因此,第二个更适合非常量 *this
13.3.3.2/3b1sb4
的对象(隐含对象参数)并用于转换为 B*
第二个check
功能。
如果您删除 const,我们将有以下候选者
B* (Host<B, D>&)
D* (Host<B, D>&)
这意味着我们不能再通过 constness 进行选择。在普通的重载解决方案中,调用现在将是模棱两可的,因为通常返回类型不会参与重载解决。然而,对于转换函数,有一个后门。如果两个转换函数同样好,那么它们的返回类型根据13.3.3/1
决定谁最好.因此,如果您要删除 const,则将采用第一个,因为 B*
更好地转换为 B*
比 D*
至B*
.
现在哪种用户定义的转换顺序更好?用于第二个或第一个检查功能的那个?规则是用户定义的转换序列只有在根据 13.3.3.2/3b2
使用相同的转换函数或构造函数时才能进行比较。 .这正是这里的情况:两者都使用第二个转换函数。请注意,因此 const 很重要,因为它强制编译器采用第二个转换函数。
既然我们可以比较它们 - 哪个更好?规则是从转换函数的返回类型到目标类型的更好转换获胜(同样是 13.3.3.2/3b2
)。在这种情况下,D*
更好地转换为 D*
比 B*
.因此选择了第一个函数,我们识别了继承!
请注意,由于我们从不需要实际上转换为基类,因此我们可以识别私有(private)继承,因为我们是否可以从 D*
转换到 B*
不依赖于根据 4.10/3
的继承形式
现在让我们假设它们没有继承关系。因此,对于第一个函数,我们有以下候选者
D* (Host<B, D>&)
第二个我们现在有了另一组
B* (Host<B, D> const&)
由于我们无法转换 D*
至B*
如果我们没有继承关系,我们现在在两个用户定义的转换序列之间没有共同的转换函数!因此,如果不是因为第一个函数是模板这一事实,我们就会模棱两可。根据13.3.3/1
,当有一个同样好的非模板功能时,模板是第二选择。 .因此,我们选择了非模板函数(第二个),我们认识到 B
之间没有继承。和 D
!
关于c++ - `is_base_of` 是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2910979/
我试图断言模板参数将派生自某个基类。但是基类是通用的,在断言的上下文中,任何特化类型之间都没有区别。我如何断言模板参数派生自任何专用类型的泛型? 我试着把它写成 base_generic: templ
给定代码: template struct Cat { ... }; template struct Bengal : Cat { ... }; template struct Persian : C
以下代码是如何工作的? typedef char (&yes)[1];typedef char (&no)[2];template <typename B, typ
我正在研究共享指针的实现。 (使用C++ 17,以防万一) 唯一的问题是转换构造函数。我希望能够将smart_ptr静态转换为基本类型的smart_ptr。 template inline smart
我有这样的层次结构: namespace MyService{ class IBase { public: virtual ~IBase(){} protected: IPointer
只是想知道为什么我不能像下面这样在 C++ 模板参数中使用 is_base_of: #include #include using namespace std; struct base { };
有没有办法判断一个基类是不是虚基类? std::is_base_of 将标识一个基类,但我正在寻找类似 std::is_virtual_base_of 的东西来标识一个虚拟基类。 这是出于 SFINA
有没有办法测试std::is_base_of什么时候A是模板类吗? template class A {}; template class B : public A {}; 我想静态测试类似 st
我正在尝试做一个结构类似于此的程序: #include template class Test {}; template class Test::value>::type> { public:
是否有可能静态断言作为模板参数提供的类型是否实现了参数包中列出的所有类型,即。参数包感知 std::is_base_of()? template class CommonBase { sta
使用下面的代码,我收到编译器投诉,称前两个模板之间对 get_code 的调用不明确。我如何编写代码来检测基类,同时还提供专门的形式?例如,如果稍后我有 class C : A {},它也应该返回 A
1. template std::true_type is_base_of_test_func( Base* ); 2. template std::false_type is_base_of
有没有办法测试std::is_base_of当A是模板类吗? template class A {}; template class B : public A {}; 我想静态测试 std::is
我对以下情况感到有点困惑,我在 is_base_of 上启用了特化。 is_base_of 需要被检查的类型的完整定义是可用的。但是,正在专门化的类型被用作正在检查的基类类型的成员 - 因此两者都需要
我遇到了模板问题: 我有两个构造函数和方法:.cpp: Cell::Cell(sf::Vector2i& uPos, sf::Vector2f& cellDimensions, std::string
我想创建一个库:- 用户通过 addCallback(Callback* callback) 添加回调(通常在第一个时间步) 之后,通常在不同的.cpp , 每当用户调用 actor() :- 如果B
我正在思考一个关于如何 is_base_of 的好问题在 boost 中实现(它决定一个给定的 class 在编译时是否是另一个 class 的基础)。 第一次看到这样的代码,我很惊讶怎么能把事情做得
我完全明白为什么这个不能工作了: class Base {}; class A; static_assert(std::is_base_of::value, ""); 因为没有关于“类层次结构”的信息
根据 C++11 标准 std::is_base_of如果 D 是从 B 派生的,或者两者是同一个非 union 类,则必须返回 true。但是在 VC++ 2010 STL 实现模板中,如果类型 B
为简洁起见,这是简化的层次结构: class IBase { public: virtual ~IBase() = 0 { }; }; // eo IBase class IDerived
我是一名优秀的程序员,十分优秀!