C++之std::is_object

相关系列文章

C++之std::is_object

C++之std::decay

C++模板函数重载规则细说

C++之std::declval

C++之std::move(移动语义)

C++之std::forward(完美转发)

C++之std::enable_if

C++之std::is_pod(平凡的数据)

目录

1.概述

2.原理分析

2.1.std::is_object

2.2.bool_constant

3.使用

4.总结


1.概述

std::is_object是一种C++类型特性,其用途是判断一个类型是否是一个对象类型(除了函数、引用和void类型)。如下例子:

#include <iostream>
#include <type_traits>

class A {};

int main() {
  std::cout << std::boolalpha;
  std::cout << "is_object:" << std::endl;
  std::cout << "int: " << std::is_object<int>::value << std::endl; //输出:true
  std::cout << "A: " << std::is_object<A>::value << std::endl;  //输出:true
  std::cout << "A&: " << std::is_object<A&>::value << std::endl; //输出:false
  std::cout << "A*: " << std::is_object<A*>::value << std::endl; //输出:true
  std::cout << "int(int): " << std::is_object<int(int)>::value << std::endl; //输出:false
  std::cout << "int(*)(int): " << std::is_object<int(*)(int)>::value << std::endl; //输出:        
                                                                                   //  true
  return 0;
}

2.原理分析

2.1.std::is_object

std::is_object的源码如下:

template <class _Ty>
constexpr bool is_object_v = !is_function_V<_Ty> && !is_reference_v<_Ty> && !is_void_v<_Ty>;

template <class _Ty>
struct is_object : bool_constant<is_object_v<_Ty>> {};

is_function_v<T> : 判断是否检查 T 是否为函数类型。如 std::function 、 lambda 、有重载 operator() 的类和指向函数指针不是函数类型。若 T 为函数类型,则提供等于 true 的成员常量 value 。否则, value 等于 false, 示例如下:

#include <type_traits> 
using namespace std; 
  
struct GeeksforGeeks { 
    int func() const&; 
}; 
  
template <typename> 
struct Computer { 
}; 
  
template <class A, class B> 
struct Computer<B A::*> { 
    using member_type = B; 
}; 
  
int x1(); 
  
int main() 
{ 
    cout << is_function<int(int)>::value << endl; //输出:true
    cout << is_function<GeeksforGeeks>::value << endl; //输出:false
    cout << is_function<int>::value << endl;   //输出:false
    cout << is_function<decltype(x1)>::value << endl;  //输出:true
  
    using A = Computer<decltype( 
        &GeeksforGeeks::func)>::member_type; 
    cout << is_function<A>::value << endl;   //输出:true
  
    return 0; 
}

is_reference_v<T> : 若 T 是引用类型(左值引用或右值引用),则提供等于 true 的成员常量 value 。对于任何其他类型, value 为 false; 示例如下:

#include <iostream>
#include <type_traits>
using namespace std;
class MyTest {
};
int main() {
   cout << "\n class TP : "<<is_reference<MyTest>::value; //输出:false
   cout << "\n class TP&: "<<is_reference<MyTest&>::value; //输出:true
   cout << "\n class TP&&: "<<is_reference<MyTest&&>::value; //输出:true
   return 0;
}

is_void_v<T> : ​检查 T 是否为 void 类型。若 T 是类型 void 、 const void 、 volatile void 或 const volatile void ,则提供等于 true 的成员常量 value。否则, value 等于 false; 示例如下:

#include <iostream>
#include <type_traits>
 
int main() 
{
    std::cout << std::boolalpha;
    std::cout << std::is_void<void>::value << '\n'; //输出:true
    std::cout << std::is_void<int>::value << '\n';  //输出:false
}

2.2.bool_constant

bool_constant是integral_constant<bool, _Val>的别名,从下面的定义可以看出:

template <bool _Val>
using bool_constant = integral_constant<bool, _Val>;

using true_type  = bool_constant<true>;
using false_type = bool_constant<false>;

那么integral_constant的定义呢?继续看下面:

template <class _Ty, _Ty _Val>
struct integral_constant {
    static constexpr _Ty value = _Val;

    using value_type = _Ty;
    using type       = integral_constant;

    constexpr operator value_type() const noexcept {
        return value;
    }

    _NODISCARD constexpr value_type operator()() const noexcept {
        return value;
    }
};

        std::integral_constant包装特定类型的静态常量,它是C++类型特征的基类。我们可以看到,这个模板类接受两个参数,一个类型_Ty和一个该类型的值_Val。它提供了一个静态的常量成员value,该成员的值就是传入的_Val;其中,using value_type = _Ty;和using type       = integral_constant;分别用来定义value的类型以及integral_constant本身的类型。

        然后,它还提供了两个转换函数,一个是constexpr operator value_type() const noexcept,可以将std::integral_constant对象隐式转换为T类型的值;另一个是constexpr value_type operator()() const noexcept,可以将std::integral_constant对象当作函数来调用,并返回其内部保存的常量。

        std::integral_constant 的两个最常用的特化版本是 std::true_type 和 std::false_type。它们是 std::integral_constant<bool, value> 的特化版本,其中 std::true_type 是 std::integral_constant<bool, true>,std::false_type 是 std::integral_constant<bool, false>。这两种类型的主要用途是表示编译期的布尔值。在模板元编程中,它们常被用来代表一种编译期的"是"和"否",从而允许我们进行编译期的条件判断。同时,由于它们都是类型,因此也可以作为类型标签来使用,帮助我们在模板元编程中传递信息。

        通过这样的设计,std::integral_constant能够让我们在编译期间就能确定某些值,从而提高代码的效率。同时,因为它包含了值类型的信息,我们还可以根据这个信息进行编程,提高代码的灵活性。

        通过上述的解释和分析,我们可以很清楚的理解了std::is_object的含义了。

3.使用

std::is_object主要用于元编程中的类型检查,以便在编译时确定某个类型是否符合限制条件。使用方法也比较简单,只需在代码中调用std::is_object<>模板,并传入要检查的类型名,即可获得该类型是否为对象类型的结果。示例如下:

template <typename T>
void calc(){
    static_assert(std::is_object<T>::value, "T must be an object type.");
    //...
}
class MyTest{};

int main(){
    calc<int>();
    MyTest x;
    func<decltype(x)>();
    calc<int&>(); //compile error
    return 0;
}

上述代码中,定义了一个模板函数calc,该函数要求其参数类型必须是对象类型。在模板函数中使用了std::is_object<>模板,来检查模板参数类型是否为对象类型。如果不是,将会抛出一个编译器错误。这样,就能够在编译期间检测到错误的使用,减少运行时错误的概率。

使用注意:1)std::is_object判断的是类型是否为对象类型,而非是否为类类型或枚举类型。  2)使用std::is_object模板时,需要注意传入的类型名中不要包含已删除的引用和cv限定符。示例如下:

#include<iostream>
#include<type_traits>

struct MyStruct{};
enum  class MyEnum{A,B};

int main(){
    std::cout << std::is_object<MyStruct>::value << std::endl; //true
    std::cout << std::is_object<MyEnum>::value << std::endl; //true
    std::cout << std::is_object<int>::value << std::endl; //true
    std::cout << std::is_object<const int>::value << std::endl; //true
    std::cout << std::is_object<const int&>::value << std::endl; //false
    std::cout << std::is_object<const volatile int>::value << std::endl; //true
    return 0;
}

4.总结

std::is_object是一个用于元编程的C++类型特性,用于判断一个类型是否是对象类型。只需在代码中调用std::is_object<>模板,并传入要检查的类型名,即可判断该类型是否为对象类型。在编写代码时,需要注意std::is_object判断的是类型是否为对象类型,而不是类类型或枚举类型。同时,在使用std::is_object模板进行类型检查时,需要注意传入的类型名中不要包含已删除的引用和cv限定符。通过合理使用std::is_object模板,可以在编译期间检测到错误的使用,减少运行时错误的概率,提高代码稳定性。

  • 39
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值