相关系列文章
目录
1.概述
std::is_object是一种C++类型特性,其用途是判断一个类型是否是一个对象类型(除了函数、引用和void类型)。如下例子:
- #include
- #include
-
- 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::value << std::endl; //输出:true
- std::cout << "A&: " << std::is_object::value << std::endl; //输出:false
- std::cout << "A*: " << std::is_object::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_function_v
- #include
- using namespace std;
-
- struct GeeksforGeeks {
- int func() const&;
- };
-
- template <typename>
- struct Computer {
- };
-
- template <class A, class B>
- struct Computer {
- using member_type = B;
- };
-
- int x1();
-
- int main()
- {
- cout << is_function<int(int)>::value << endl; //输出:true
- cout << is_function
::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::value << endl; //输出:true
-
- return 0;
- }
is_reference_v
- #include
- #include
- using namespace std;
- class MyTest {
- };
- int main() {
- cout << "\n class TP : "<
::value; //输出:false - cout << "\n class TP&: "<
::value; //输出:true - cout << "\n class TP&&: "<
::value; //输出:true - return 0;
- }
is_void_v
- #include
- #include
-
- 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
- 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
通过这样的设计,std::integral_constant能够让我们在编译期间就能确定某些值,从而提高代码的效率。同时,因为它包含了值类型的信息,我们还可以根据这个信息进行编程,提高代码的灵活性。
通过上述的解释和分析,我们可以很清楚的理解了std::is_object的含义了。
3.使用
std::is_object主要用于元编程中的类型检查,以便在编译时确定某个类型是否符合限制条件。使用方法也比较简单,只需在代码中调用std::is_object<>模板,并传入要检查的类型名,即可获得该类型是否为对象类型的结果。示例如下:
- template <typename T>
- void calc(){
- static_assert(std::is_object
::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
- #include
-
- struct MyStruct{};
- enum class MyEnum{A,B};
-
- int main(){
- std::cout << std::is_object
::value << std::endl; //true - std::cout << std::is_object
::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模板,可以在编译期间检测到错误的使用,减少运行时错误的概率,提高代码稳定性。
评论记录:
回复评论: