c++ - 如何测试结构的成员是否已定义 (c++)

标签 c++

<分区>

我正在尝试测试在调用函数之前是否定义了声明为指向 void 的指针的结构成员。但是,似乎每当我向基本程序添加任何额外内容(例如末尾的 std::cout)时,“testB”总是等于 true。我无法更改“struct a”的声明方式,因为它是外部库的一部分。

那么,我该如何测试声明为 void 指针的结构成员实际上是否使用正确的类型定义?

示例结构

struct b { };

struct a {
   void *b;
};

我正在尝试测试的示例代码

struct a myA;
struct b myB;
myA.b = &myB;
foo(myA);

失败的示例测试程序

#include <iostream>

int main() {

   struct a aa;
   struct b bb;
   // the following line is commented out so I'm expecting 'testB' to evaluate to false
   // aa.b = &bb;

   struct b *testB = static_cast<struct b*>(aa.b);

   if(testB) {
      std::cout << "is defined" << std::endl;
   } else {
      std::cout << "is not defined" << std::endl;
   }

   std::cout << "why does adding this line out result in testB equating to true" << std::endl;

   return 0;
}

最佳答案

这是一个有趣的问题,因为您在问两个问题:

  • 是否输入 T有一个名为 b 的成员?
  • 如果前一个为真,则该成员类型为 void*

我们可以在编译时完成所有这些。

在您的解决方案中,您不应尝试执行静态转换,因为您冒着违反别名规则的风险,并且您还假设静态成员首先出现。

我们可以使用一个简单的检测习语来检测条件是否满足:

template<class T, class=void>
struct has_void_ptr_member_named_b_t : std::false_type{};

template<class T>
struct has_void_ptr_member_named_b_t<T, std::void_t<decltype(std::declval<T>().b)>> : 
    std::is_same<std::decay_t<decltype(std::declval<T>().b)>, void*>
{};
template<class T>
constexpr bool has_void_ptr_member_named_b_v = has_void_ptr_member_named_b_t<T>::value;

现在你可以问has_void_ptr_member_named_b_v可以转换为 bool ,对于任何给定类型 T

例如:

struct b { };
struct a {
   void *b;
};
// ...

std::cout << std::boolalpha << has_void_ptr_member_named_b_v<a> << std::endl; // true
std::cout << std::boolalpha << has_void_ptr_member_named_b_v<b> << std::endl; // false

Demo

它的 std:void_t 使用 C++17 ,这很容易自己创建。我认为,如果你足够努力,你可以在 C++11 中实现所有这些。您还可以查看 std::experimental::is_detected如果您想使用预制的检测惯用语(目前是非标准的)。


正如@YSC 在下面的评论中指出的,也许您只是想测试是否 aa.b是非空的吗?

您应该将其初始化为 nullptr因为,作为基本类型(指针),它没有默认构造函数,并且保持未初始化状态:

struct a {
   void *b = nullptr;
};

您仍然应该避免强制转换,因为您冒着未定义行为的风险,并且您假设结构始终对齐。

a aa;
b bb;
auto test = [&aa](){
    if (aa.b)
        std::cout << "aa.b is defined\n";
    else
        std::cout << "aa.b is null\n";
};
test(); // "aa.b is null"
aa.b = &bb;
test(); // "aa.b is defined"

Demo 2

关于c++ - 如何测试结构的成员是否已定义 (c++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49881301/

相关文章:

c++ - 在布局中的 QLabel 上设置文本,不会调整大小

c++ - 在c++中绘制抗锯齿圆角矩形

c++ - 删除 vector 中指针的方法 [C++]

c++ - 错误 'LC_TYPE' 未在此范围内声明

c++ - key 存在于 map 变量中,但 find 找不到它

c++ - 将具有多个键的 perl 映射转换为 C++

c++ - 为什么当我将 int 乘以 double 时会得到错误的值?

c++ - C++中公共(public)继承基类调用派生类的私有(private)虚函数

c++ - 重载解析和用户定义转换

c++ - Boost 中的 DEFINE_TYPE_NAME 是如何工作的?