类的成员检查问题详解[CPP template-7]

还记得我们在std::declval详解[CPP template-4]https://blog.csdn.net/FlamBoyanceI/article/details/140887154 这篇文章的结尾提到的那个问题吗?如何做类的成员检查?又怎么把这个检查的流程方便化?(这里我使用的C++17的思路,concept的使用留到以后再讲)

固定的类型成员判断

下面的例子来自CPP TEMPLATE这本书上。不过我稍作修改,让它更简单易懂。这是我们更复杂的应用的基础,先把这个看懂吧

#include <conio.h>
#include <graphics.h>
#include <vector>
#include <iostream>


template <typename T>
bool test(typename T::X const* hello)
{

	return true;
}

template <typename T>
bool test(...) 
{
	return false;
}

#define member_or_not(T)    test<T>(0)
//0到空指针常量的转化要优先于匹配给省略号参数
struct strt
{
	using X = double;
};

int main()
{
	std::cout << member_or_not(strt) << std::endl;
	std::cout << member_or_not(int) << std::endl;
}

指定的类型成员判断

例子

上面我们只能把判断对象写死在代码中,但是如果我们希望更灵活的去判断成员,就需要借助宏的能力。
巧妙的使用宏,可以生成我们希望的代码

struct MyType {
    int foo() {
        return 1;
    }
};
//##是CPP提供的文字处理工具,可以将字符粘连
#define DEFINE_HAS_MEMBER_FUNCTION_CHECK(MemberFunctionName) \
template <typename T> \
auto check_##MemberFunctionName(int) -> decltype(std::declval<T>().MemberFunctionName(), std::true_type()); \
\
template <typename T> \
auto check_##MemberFunctionName(...) -> std::false_type;

//宏的使用方法
DEFINE_HAS_MEMBER_FUNCTION_CHECK(foo)

int main() {
    std::cout << std::boolalpha;
    std::cout << "Has foo(): " << decltype(check_foo<MyType>(0))::value << std::endl;  // true
    std::cout << "Has foo(): " << decltype(check_foo<int>(0))::value << std::endl;     // false
    return 0;
}
全类型判断最终答案

这里是判断成员函数,成员变量(都是非静态),以及嵌套类(或者类型成员)的存在性判断方法【静态成员变量和静态成员函数可以模仿】

这里的解决方案是基于逗号匹配空间的芳芳

#include <iostream>

struct MyType {
    int amember;
    using typeda = double;
    int foo() {
        return 1;
    }
};

//这里是用模板去判断成员函数的存在性
//------------------------------------------------------------------

#define DEFINE_HAS_MEMBER_FUNCTION_CHECK(MemberFunctionName) \
template <typename T> \
auto check_##MemberFunctionName(int) -> decltype(std::declval<T>().MemberFunctionName(), std::true_type()); \
\
template <typename T> \
auto check_##MemberFunctionName(...) -> std::false_type;

DEFINE_HAS_MEMBER_FUNCTION_CHECK(foo)

//--------------------------------------------------------------------
//用模板去判断成员变量的存在性
#define DEFINE_HAS_DATA_MEMBER_CHECK(DATAMemberName) \
template <typename T> \
auto check_##DATAMemberName(int) -> decltype(std::declval<T>().DATAMemberName, std::true_type()); \
\
template <typename T> \
auto check_##DATAMemberName(...) -> std::false_type;


DEFINE_HAS_DATA_MEMBER_CHECK(amember)
//-------------------------------------------------------------------
//用模板去判断类型成员的存在性
#define DEFINE_HAS_TYPE_MEMBER_CHECK(TYPEMemberName) \
template <typename T> \
auto check_##TYPEMemberName(int) -> decltype(std::declval<T::TYPEMemberName>(), std::true_type()); \
\
template <typename T> \
auto check_##TYPEMemberName(...) -> std::false_type;

DEFINE_HAS_TYPE_MEMBER_CHECK(typeda)
//------------------------------------------------------------------

int main() {
    std::cout << std::boolalpha;
    std::cout << "Has foo(): " << decltype(check_foo<MyType>(0))::value << std::endl;  // true
    std::cout << "Has foo(): " << decltype(check_foo<int>(0))::value << std::endl;     // false

    std::cout << "Has amember: " << decltype(check_amember<MyType>(0))::value << std::endl; // true
    std::cout << "Has amember: " << decltype(check_amember<int>(0))::value << std::endl;    // false

    std::cout << "Has amember: " << decltype(check_typeda<MyType>(0))::value << std::endl;  // true
    std::cout << "Has amember: " << decltype(check_typeda<int>(0))::value << std::endl;     // false

    return 0;
}

好,今天就写到这里,相信看完的你一定对模板编程中的匹配问题有了更深层次的认知吧ψ(`∇´)ψ

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值