c++ 检测成员函数_C/C++_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > C/C++ > c++ 检测成员函数

c++ 检测成员函数

 2019/1/20 23:32:32  tcspecial  程序员俱乐部  我要评论(0)
  • 摘要:C++没有类似Java反射机制,无法动态获取对象元信息,那么如何检测对象是否存在成员函数呢?1.检测是否存在特定成员函数muduo框架中有这样一段代码:vimuduo/base/Singleton.htemplate<typenameT>structhas_no_destroy{template<typenameC>staticchartest(decltype(&C::no_destroy));//返回chartemplate<typenameC>
  • 标签:检测 函数 c++

C++ 没有类似Java反射机制,无法动态获取对象元信息,那么如何检测对象是否存在成员函数呢?

?

1. 检测是否存在特定成员函数

muduo框架中有这样一段代码:

vi muduo/base/Singleton.h

class="cpp" name="code">template<typename T>
struct has_no_destroy
{
  template <typename C> 
  static char test(decltype(&C::no_destroy));	// 返回char

  template <typename C> 
  static int32_t test(...);		// 返回int

  const static bool value = sizeof(test<T>(0)) == 1;
};

static void init()
{
	value_ = new T();

	// 判断是否存在no_destroy方法
	if (!detail::has_no_destroy<T>::value)
	{
	  ::atexit(destroy);
	}
}

?

?测试代码:

struct A
{
	// empty
};

struct B
{
	int no_destroy;		// 成员变量	
};

struct C
{
	int no_destroy(){}	// 成员函数
};

void test()
{
	// 匹配test(&A::no_destroy) 时,由于A没有no_destroy方法,理论上应该报错。编译器寻找下一个匹配test(...),因此返回0
	bool p1 = has_no_destroy<A>::value;
	bool p2 = has_no_destroy<B>::value;
	bool p3 = has_no_destroy<C>::value;
	printf("%d %d %d\n", p1, p2, p3); 	// 输出 0 1 1
}

?

上文利用了c++ SFINAE(Substition Failure is not a error) 特性语法,即匹配失败不是错误。在进行模板特化,编译器会返回最佳匹配模板,避免失败。

?

2.?增强版本

上述代码,B的no_destroy成员也可以正常调用,那如何只检测成员函数呢?

成员函数要用对象来调用,可用declval构造对象。

struct check_no_destroy
{
	/**
	 * 1. T 对象
	 * 2. U 获取T::no_destroy()返回值
	 * 3. 返回值类型为int
	 */
	template <typename T, 
	typename U = typename std::decay<decltype(std::declval<T>().no_destroy())>::type, 
	typename = typename std::enable_if<std::is_same<int, U>::value>::type>	
	static std::true_type Test(int);

	template <typename>
	static std::false_type Test(...);
};

template <typename T>
struct has_no_destroy :
 public decltype(check_no_destroy::Test<T>(0))
{
	
};

void test()
{
	/*
	std::true_type = integral_constant<bool, true>;
	显示值::value
	*/

	bool p = hash_no_destroy<D>::value;
	cout << p << endl;		// 1 
}

?

3. std::declval

std::declval 返回对象的右值引用,不管对象是否有构造函数,一般配合decltype使用。

struct MyOb
{
	MyObj1(){ cout << "Constuctor" << endl; }
	int foo() const { return 1; }
};

struct MyObj
{
	MyObj(const MyObj&){}
	int foo() const { return 1; }
};

void test()
{
	decltype(MyOb().foo()) n0 = 1;					// ok, 构造函数不会调用
	decltype(MyObj().foo()) n1 = 1;					// 编译错误,MyObj没有默认构造函数
	decltype(std::declval<MyObj>().foo()) n2 = 2;	                // ok, int
	cout << typeid(n2).name() << endl;				// i
}

?

?

?

?

?

上一篇: 简谈Java的join()方法 下一篇: 没有下一篇了!
发表评论
用户名: 匿名