Dan*_*aum 8 c++ stl type-traits c++11 visual-studio-2015
我当前的问题的灵感来自于试图理解如何std::unique_ptr<T, D>利用模板机制实例化一个模板类,其大小为何T*时D(删除器类型)是一个lambda函数类型,但是当D一个函数指针类型时它是一个更大的大小(因为空间需要在unique_ptr实例中分配以存储函数指针).
通过VS2015源代码,我发现std::unique_ptr派生自std::_Unique_ptr_base,而后者又声明了类型的数据成员_Compressed_pair<class _Ty1, class _Ty2, bool = is_empty<_Ty1>::value && !is_final<_Ty1>::value>.类型_Ty1在后一种情况下是删除器的类型,D即该第二unique_ptr在前面段落中提到的模板参数; 也就是说,这个问题背后的动机是我对比_Ty1是一种lambda类型,而_Ty1不是函数指针类型.(实际上,bool正在使用默认值.)
我认识到,is_empty<_Ty1>::value是true当_Ty1是λ类型的实例(当拉姆达没有捕获的变量,因此具有0的大小); 但它是false何时_Ty1是函数指针类型.
这导致我追求如何std::is_empty定义.
啊!
以下是std::is_empty我在VS2015 C++库源代码中可以找到的完整实现.
在文件中type_traits是这样的:
// TEMPLATE CLASS is_empty
template<class _Ty>
struct is_empty _IS_EMPTY(_Ty)
{ // determine whether _Ty is an empty class
};
Run Code Online (Sandbox Code Playgroud)
...并且宏_IS_EMPTY在同一个文件中定义:
#define _IS_EMPTY(_Ty) \
: _Cat_base<__is_empty(_Ty)>
Run Code Online (Sandbox Code Playgroud)
......此时我的运气很干,因为我无法找到__is_empty任何地方的定义.我已经通过整个VS2015安装目录(其中包括,包括所有C++库源代码,包括 - 虽然也许我错了)进行了GREP.
我喜欢在我想要的时候理解C++内部.但是......我坚持这个,并且大量的谷歌搜索没有透露答案(虽然我已经看到了对内在函数的引用),而我的挖掘还没有...发现任何源代码.
有人可以启发这种情况吗?如何std::is_empty<T>在VS2015中实际实现,或者,对于任何其他编译器?
看起来好像MSVC++提供了内在__isempty(T)而不是处理库级实现.由于T传递给的参数类型std::is_empty<T>可以final,我不认为可以有安全的库实现,可能需要编译器帮助.
T在我能想到的库中确定某个类型是否为空的唯一方法是这个(专门化处理的非class类型std::is_empty<T>不是true):
template <bool, typename T>
struct is_empty_aux: T { unsigned long long dummy; };
template <typename T>
struct is_empty_aux<false, T> { unsigned long long dummy[2]; };
template <typename T>
struct is_empty:
std::integral_constant<bool,
sizeof(is_empty_aux<std::is_class<T>::value, T>)
== sizeof(unsigned long long)> {
};
Run Code Online (Sandbox Code Playgroud)
但是,如果T是final在继承is_empty_aux是非法的.虽然final可以使用std::is_final<T>我检测类的情况,但我没有看到确定其对象是否为空的方法.因此,使用编译器内在可能是必要的.无论如何,编译器内在函数对于某些其他类型特征肯定是必需的.编译器内在函数是编译器神奇地提供的声明/定义:它们通常既未显式声明也未定义.编译器具有关于类型的必要知识,并通过内在函数公开这些知识是一种合理的方法.