还记得我们在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;
}
好,今天就写到这里,相信看完的你一定对模板编程中的匹配问题有了更深层次的认知吧ψ(`∇´)ψ