Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mechanism to check if a C++ member is private

I am writing unit tests for undergraduate students and want to enforce certain members as public or private. I am aware of methods to actually test private members, e.g., #define private public or using a friend class, but have not seen anything that would allow me to check exactly if a member is private or not.

A brute force method would be trying a compile and parsing the output error, e.g., look for something like error: 'foo' is a private member of 'Bar', but I am hoping someone will have a better trick!

like image 686
Connor Fuhrman Avatar asked Sep 28 '20 02:09

Connor Fuhrman


People also ask

What is private member function in C?

Private: The class members declared as private can be accessed only by the member functions inside the class. They are not allowed to be accessed directly by any object or function outside the class. Only the member functions or the friend functions are allowed to access the private data members of the class.

How do I access private data members?

The private data members cannot be accessed from outside the class. They can only be accessed by class or friend functions. All the class members are private by default.

How is a private member of a class defined?

Class members in C++ are private by default that means you cannot access them by any outside object (in main). If you define[not just declare] the setTime function within your class, which is a friend function to the private members, you can initialize your private members using an object as well in main.

How to access private members of a class in C++?

A class in C++ has public, private and protected sections which contain the corresponding class members. The private data members cannot be accessed from outside the class. They can only be accessed by class or friend functions.

What is private and protected members in C++?

Private and Protected Members in C++. A class in C++ has public, private and protected sections which contain the corresponding class members. The private data members cannot be accessed from outside the class. They can only be accessed by class or friend functions. All the class members are private by default.

What is the difference between a private specifier and a member?

Members defined after the private specifier are accessible to member functions only and can’t be referred directly from the code that uses the class. A class is usually constructed with two sides in mind - the designer of the class and the user of the class.

How to modify private members of a class in Java?

private members can be modified using the class interface functions, e.g changeUsername function takes string argument from the user of the class and it stores its value to the private member - username. Note that there is also a friend keyword that distinguishes other classes and functions allowed to access the private members of the class.


2 Answers

If you want to assert that a type Bar doesn't have a public member named foo, you can write the following test:

template<typename T> constexpr auto has_public_foo(T const &t) -> decltype(t.foo, true)  {     return true; }  constexpr auto has_public_foo(...)  {     return false; }  static_assert(not has_public_foo(Bar{}), "Public members are bad practice"); 

Here's a demo.

like image 100
cigien Avatar answered Sep 27 '22 18:09

cigien


You can use the AST output of the Clang compiler to validate that a certain member is private or public. For example, for the following code:

class test { public:     int pub; private:     int prv; }; 

Running this command: clang -Xclang -ast-dump -fsyntax-only t.cpp

gives the AST dump:

TranslationUnitDecl 0x55f6f550e3f8 <<invalid sloc>> <invalid sloc> |-TypedefDecl 0x55f6f550e9b0 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128' | `-BuiltinType 0x55f6f550e690 '__int128' |-TypedefDecl 0x55f6f550ea20 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128' | `-BuiltinType 0x55f6f550e6b0 'unsigned __int128' |-TypedefDecl 0x55f6f550ed68 <<invalid sloc>> <invalid sloc> implicit __NSConstantString '__NSConstantString_tag' | `-RecordType 0x55f6f550eb10 '__NSConstantString_tag' |   `-CXXRecord 0x55f6f550ea78 '__NSConstantString_tag' |-TypedefDecl 0x55f6f550ee00 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *' | `-PointerType 0x55f6f550edc0 'char *' |   `-BuiltinType 0x55f6f550e490 'char' |-TypedefDecl 0x55f6f5545bf8 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list '__va_list_tag [1]' | `-ConstantArrayType 0x55f6f5545ba0 '__va_list_tag [1]' 1 |   `-RecordType 0x55f6f550eef0 '__va_list_tag' |     `-CXXRecord 0x55f6f550ee58 '__va_list_tag' `-CXXRecordDecl 0x55f6f5545c50 <t.cpp:1:1, line:6:1> line:1:7 class test definition   |-DefinitionData pass_in_registers trivially_copyable trivial literal   | |-DefaultConstructor exists trivial needs_implicit   | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param   | |-MoveConstructor exists simple trivial needs_implicit   | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param   | |-MoveAssignment exists simple trivial needs_implicit   | `-Destructor simple irrelevant trivial needs_implicit   |-CXXRecordDecl 0x55f6f5545d78 <col:1, col:7> col:7 implicit class test   |-AccessSpecDecl 0x55f6f5545e10 <line:2:1, col:7> col:1 public   |-FieldDecl 0x55f6f5545e50 <line:3:5, col:9> col:9 pub 'int'   |-AccessSpecDecl 0x55f6f5545e98 <line:4:1, col:8> col:1 private   `-FieldDecl 0x55f6f5545ed8 <line:5:5, col:9> col:9 prv 'int' 

which is quite simple to parse by a script. Or you can use the Clang AST library to create LibASTMatcher to validate using data itself as described in the documentation.

like image 20
Slava Avatar answered Sep 27 '22 19:09

Slava