如何在VS2015(或任何编译器)中实现std :: is_empty <t>?

时间:2016-02-21 01:43:06

标签: c++ c++11 stl visual-studio-2015 typetraits

当前问题的灵感来自于std::unique_ptr<T, D>T*(删除类型)是lambda时,D如何利用模板机制来实例化D大小的模板类函数类型,但unique_ptr是函数指针类型时的大小(因为需要在std::unique_ptr实例中分配空间来存储函数指针)。

通过VS2015源代码,我发现std::_Unique_ptr_base派生自_Compressed_pair<class _Ty1, class _Ty2, bool = is_empty<_Ty1>::value && !is_final<_Ty1>::value>,后者又声明了_Ty1类型的数据成员。后一个上下文中的类型D是删除者的类型unique_ptr,这是前一段中提到的第二个_Ty1模板参数;也就是说,这个问题背后的动机是我将_Ty1与lambda类型进行对比,而bool是一个函数指针类型。 (事实上​​,正在使用is_empty<_Ty1>::value的默认值。)

true是lambda类型的实例时(当lambda没有捕获变量,因此大小为0时),我认识到_Ty1false;但是当_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 }; 中是:

_IS_EMPTY

...宏#define _IS_EMPTY(_Ty) \ : _Cat_base<__is_empty(_Ty)> 在同一个文件中定义:

__is_empty

...此时我的运气不干,因为我无法在任何地方找到std::is_empty<T>的定义。我已经通过整个VS2015安装目录(其中包括,包括所有C ++库源代码,包括在内 - 但也许我错了)。

我喜欢在我想要的时候理解C ++内部。但是......我坚持这个,大量的谷歌搜索没有透露答案(虽然我已经看到了内在函数的参考),而我的挖掘并没有...发现任何源代码。

有人可以启发这种情况吗? # For each tuple inside daily_sales for sale in daily_sales: # Use the first element of that tuple as a key and check if it's inside the dictionary budgeted_sales if sale[0] in budgeted_sales: # Compare the value stored for that key with the second element of the tuple (which contains the other price) and print stuff if budgeted_sales[sale[0]] > sale[1]: print('Over') else: print('Under') 如何在VS2015中实际实现,或者,对于任何其他编译器?

2 个答案:

答案 0 :(得分:7)

看起来好像MSVC ++提供了内在的__isempty(T),而不是处理库级实现。由于传递给T的参数类型std::is_empty<T>可以是final,因此我认为不存在安全的库实现,并且可能需要编译器帮助。

确定某个类型T在我能想到的库中是否为空的唯一方法是这种情况(专门化处理非class类型std::is_empty<T>不是{ {1}}):

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)> { }; T,则final中的继承是非法的。虽然可以使用is_empty_aux检测final类的情况,但我没有看到确定其对象是否为空的方法。因此,使用编译器内在可能是必要的。无论如何,编译器内在函数对于某些其他类型特征肯定是必需的。编译器内在函数是编译器神奇地提供的声明/定义:它们通常既未显式声明也未定义。编译器具有关于类型的必要知识,并通过内在函数公开这些知识是一种合理的方法。

答案 1 :(得分:1)

还遇到了这个问题并看了一下Ubuntu 14.04中的gcc 4.8头文件。事实上,有一个家庭,如__is_empty__is_pod__is_polymorphic等,以这种方式使用

// /usr/include/c++/4.8/type_traits:516
template<typename _Tp>
struct is_empty
    : public integral_constant<bool, __is_empty(_Tp)>
{};

他们似乎没有包含任何C ++标题。我已经尝试过g ++和clang ++来编译这段代码

#include <stdio.h>

struct X {};

int main()
{
    printf("%d %d %d\n", __is_empty(X), __is_enum(X), __is_class(X));
    return 0;
}

我觉得不常见的是它们看起来像函数但实际上是将类型作为参数而不是实例(如果你尝试X x; __is_empty(x);则不行。)