【问题标题】:Check if a class has a pointer data member检查一个类是否有指针数据成员
【发布时间】:2014-02-01 13:06:12
【问题描述】:

有没有办法测试一个类是否有指针数据成员?

class Test
{
  int* p;
}

template< typename T >
foo( T bla )
{
}

这不应该编译。因为Test有一个指针数据成员。

Test test;
foo( test )

也许我可以使用 trait 来禁用模板?还是我唯一的选择宏?也许有人知道boost是否可以做到?

【问题讨论】:

  • 你需要为 foo() 声明返回类型。
  • 您真正想在模板函数中做什么?它如何与类中的指针相关联?
  • 为什么不应该编译?
  • @Ahmed 因为缺少分号 :) 说真的,他想说“我想静态断言该类没有指针成员”

标签: c++ boost c++11 sfinae


【解决方案1】:

以下可以起到保护作用,但成员变量必须是可访问的(public),否则不起作用:

#include <type_traits>

class Test
{
public:
  int* p;
};

template< typename T >
typename std::enable_if< std::is_pointer< decltype( T::p ) >::value >::type
foo( T bla ) { static_assert( sizeof( T ) == 0, "T::p is a pointer" ); }

template< typename T >
void foo( T bla )
{
}

int main()
{
    Test test;
    foo( test );
}

Live example

当然你需要知道要检查的成员变量的名称,因为 C++ 中没有内置的通用反射机制。


另一种避免歧义的方法是创建一个has_pointer 助手:

template< typename, typename = void >
struct has_pointer : std::false_type {};

template< typename T >
struct has_pointer< T, typename std::enable_if<
                         std::is_pointer< decltype( T::p ) >::value
                       >::type > : std::true_type {};

template< typename T >
void foo( T bla )
{
    static_assert( !has_pointer< T >::value, "T::p is a pointer" );
    // ...
}

Live example

请注意,我只是在函数的第一行添加了一个static_assert,以获得一个漂亮、易读的错误消息。当然,您也可以通过以下方式禁用该功能本身:

template< typename T >
typename std::enable_if< !has_pointer< T >::value >::type
foo( T bla )
{
    // ...
}

【讨论】:

  • 也许您应该消除对 foo 的调用中的歧义。
  • @dyp 更新了答案,展示了改善错误/超导情况的两种方法。
  • 当然,这是假设只有一个成员,它的名字应该是p。
  • 感谢您的回答。我想知道是否有办法检查我们不知道名称的指针数据成员。我以 p 为例,但我的想法是我不知道名称是什么,或者是否只有 1 个指针数据成员。 (与@sehe 提到的相同)
  • @user985611 正如我已经在答案中写的那样,您必须知道名称,因为 C++ 没有通用反射机制。对不起。
【解决方案2】:

我想知道是否有办法检查我们不知道名称的指针数据成员。我以 p 为例,但我的想法是我不知道名称是什么,或者是否只有 1 个指针数据成员

我不认为你可以。

您可以使用 gcc 的 -Weffc++,它会警告带有指针成员的类(没有定义最少的特殊成员)。

不过,我真正认为您想要的是“这个类是否具有值语义”(“我是否需要深度克隆它”)。在 C++ 中,您必须假设这一点,除非禁止复制/赋值

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-19
    • 1970-01-01
    • 2017-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多