首页 > 其他分享 >Detecting Members

Detecting Members

时间:2023-09-10 13:04:58浏览次数:41  
标签:FUNCTION Function struct MyTest ## Init Members Detecting

在编译期判断类内是否存在某个成员或者成员函数,在模板编程中比较常见。

Detecting Nontype Member

namespace NontypeMember {      
     
#define HAS_MEMBER(Member) \     
template<typename T, typename = std::void_t<>> \     
struct Has##Member : std::false_type { \     
}; \     
template<typename T> \     
struct Has##Member<T, std::void_t<decltype(T::Member)>> : std::true_type { \     
};     
     
#define CHECK_MEMBER(T, Member) \     
Has##Member<T>::value     
     
HAS_MEMBER(id)     
HAS_MEMBER(name)     
     
struct MyTest {     
    int id;     
};     
     
}     
    
TEST(testCase, NontypeMember)       
{     
    using namespace NontypeMember;     
    static_assert(CHECK_MEMBER(MyTest, id), "hase no m_member");     
    static_assert(!CHECK_MEMBER(MyTest, name), "hase no m_member");     
}

利用SFINE进行判断,在c++20中可以通过concepts来实现。

Detecting Funtion Member

namespace FunctionMember {     
    
#define HAS_FUNCTION(Function, ...) \     
template<typename T, typename = std::void_t<>> \            
struct Has##Function : std::false_type { \    
}; \     
template<typename T> \     
struct Has##Function<T, std::void_t<decltype(std::declval<T>().Function())>> : std::true_type { \    
};   

#define CHECK_FUNCTION(T, Function) \              
Has##Function<T>::value                                                                                      
HAS_FUNCTION(Init)                                                                               
HAS_FUNCTION(DeInit)                                                                                   
struct MyTest {   
    int id;   
    void Init() {}           
};
      
}     
    
TEST(testCase, FunctionMember)     
{     
    using namespace FunctionMember;    
    static_assert(CHECK_FUNCTION(MyTest, Init), "hase no m_member");            
    static_assert(!CHECK_FUNCTION(MyTest, DeInit), "hase no m_member");         
}

How to detect private member?

通过上面的常用手法可以满足常见的应用场景,但是可以发现上面检测的member均为public成员,那么进一步想检测是否存在某个私有成员变量或者成员函数应该如何操作?我们基于上面的例子进行改造:

struct MyTest {                                                                             
private:
    int id; 
    void Init() {}           
};

则发现出现了误报:

static_assert(CHECK_FUNCTION(MyTest, Init), "hase no m_member"); // 无法检测到Init成员

这时由于Init成员函数为私有,因此HasInit无法匹配到特化版本,匹配到泛化版本因此为false;

可以尝试使用:decltype(std::declval<MyTest>().Init()) ,则会提示报错:

MyTest::Init() is private within this context

那如何解决?在cppreference中有这么一句神奇的说明:

Explicit instantiation definitions ignore member access specifiers: parameter types and return types may be private.

即显式实例化定义忽略成员访问说明符:参数类型和返回类型可能是私有的,改造代码为:

namespace FunctionMember {     

#define HAS_FUNCTION(Function, ...) \     
template<typename T, typename = std::void_t<>> \            
struct Has##Function : std::false_type { \    
}; \
template<typename T> \ 
struct Has##Function<T, std::void_t<decltype(std::declval<T>().Function())>> : std::true_type { \    
}; \
template <auto hasResult> \
struct HasImpl##Function { \   
    constexpr static auto value = hasResult; \      
};

#define HAS_FUNCTION_INS(T, Function) \      
template struct HasImpl##Function<Has##Function<T>::value>;  // 关键点

#define CHECK_FUNCTION(T, Function) \
HasImpl##Function<Has##Function<T>::value>::value

HAS_FUNCTION(Init)
HAS_FUNCTION(DeInit)

struct MyTest {
private:
    int id;
    void Init() {}
};
HAS_FUNCTION_INS(MyTest, Init);
HAS_FUNCTION_INS(MyTest, DeInit);

}

TEST(testCase, FunctionMember)
{
    using namespace FunctionMember;
    static_assert(CHECK_FUNCTION(MyTest, Init), "hase no m_member");  // 编译期检测私有成员函数是否存在
    static_assert(!CHECK_FUNCTION(MyTest, DeInit), "hase no m_member");
}

通过显示实例化触发成员函数或者成员变量的检测,并存储检测结果并在编译期判断。

参考资料

【1】https://en.cppreference.com/w/cpp/language/class_template

标签:FUNCTION,Function,struct,MyTest,##,Init,Members,Detecting
From: https://blog.51cto.com/u_13137973/7424429

相关文章

  • 将MembershipCreateStatus枚举成员翻译成自定义信息
    publicstaticclassAccountValidation{publicstaticstringErrorCodeToString(MembershipCreateStatuscreateStatus){switch(createStatus){caseMembershipCreateStatus.DuplicateUserName:......
  • Probabilistic and Geometric Depth: Detecting Objects in Perspective(1)
    作者认为单目3D目标检测可以简化为深度估计问题,深度估计不准确限制了检测的性能.已有的算法直接使用孤立实例或者像素估计深度,没有考虑目标之间的集合关系,因此提出了构建预测的目标之间的几何关系图,来促进深度预测.将深度值划分成若干个区间,然后通过分布的期望来计算深度值......
  • Compose 状态保存:rememberSaveable 原理分析
    前言我曾经在一篇介绍ComposeNavigation的文章中提到了Navigation的状态保存实际是由rememberSaveable实现的,有同学反馈希望单独介绍一下rememberSaveable的功能及实现原理。我们都知道remember可以保存数据、避免状态因重组而丢失,但它依然无法避免在ConfigurationCha......
  • nonstatic data members 和 static data members
    在C++中,类的数据成员可以分为非静态数据成员(non-staticdatamembers)和静态数据成员(staticdatamembers)。非静态数据成员(non-staticdatamembers):非静态数据成员是类定义中没有使用static关键字声明的数据成员。对于这些数据成员,每个类的实例都有各自独立的内存空间,它们在对象......
  • 【cpluscplus教程翻译】Special members
    特殊成员特殊成员函数是那些在特定情况被隐式定义的成员函数:默认构造、析构、拷贝构造、拷贝赋值、移动构造、移动赋值(注意构造和赋值的区别,只要是内存有没有新增),让我们逐个学习一下默认构造函数(defaultconstructor)默认构造函数在没给任何参数初始化对象时调用如果一个类的......
  • Expression-bodied members (=>)
    C#中有一种简写方式叫做expressionbody https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/expression-bodied-members即使用操作符=>代替只有一行代码的一些场合,省去了return即{},坦率的说我不是很喜欢这些语法糖,但......
  • Detecting novel systemic biomarkers in external eye photos
    FRIDAY,MARCH24,2023PostedbyBorisBabenko,SoftwareEngineer,andAkibUddin,ProductManager,GoogleResearch Lastyearwepresented results demo......
  • 【五期邹昱夫】CCF-A(SIGSAC'22)Membership Inference Attacks by Exploiting Loss Traj
    "Liu,Yiyong,etal."Membershipinferenceattacksbyexploitinglosstrajectory."Proceedingsofthe2022ACMSIGSACConferenceonComputerandCommunicatio......
  • 【五期邹昱夫】CCF-A(ICCV'21)On the Difficulty of Membership Inference Attacks
    "Rezaei,Shahbaz,andXinLiu."Onthedifficultyofmembershipinferenceattacks."ProceedingsoftheIEEE/CVFConferenceonComputerVisionandPatternRec......
  • E - Dividing Chocolate --- detecting next end point by double expand & half fold
    E-DividingChocolatehttps://atcoder.jp/contests/abc159/tasks/abc159_e 思路对于不大于k位置的查找,前一篇给出了基于前缀和的从左向右逐步查找方法https://ww......