Property implementation in C ++
Hello! When implementing projects, developers often need classes that contain only fields and do not have any functions. Such classes are useful for storing the necessary information with their subsequent manipulations.
The first approach to implementing such classes is based on the use of C structures. As a drawback of this approach, it is that all fields are writable and readable, which is not always good.
The second approach is based on hiding all fields and providing getters and setters for the fields. This approach is vividly used in the Java language. As an advantage, we can control the access to fields. The disadvantages include the fact that the class becomes large, and getters and setters do not carry a logical burden.
If the field is a class type, sometimes you need to set the object by value, by lvalue-link, by rvalue-link. And also using const / volatile modifiers.
Many languages support properties as a language feature. Writing code becomes cleaner and more reliable. To simplify the writing of getters and setters, you can use macros to generate code.
But using macros is dangerous. We may not correctly indicate the type (type) or a variable of the wrong type (name). In the best case, we get a runtime error when using getters and setters. In the worst case, the error will remain.
I wanted us to be able to generate getters and setters, but at the same time we could check the correctness of type (type), the correctness of the type with a variable (name) and that the types were equal. And this can be done starting with C ++ 11 using the type_traits standard library.
Using this approach, you can implement getters and setters for all types of class fields.
All macros for getters and setters implemented in the form of a header-only library. By connecting only one header file, you can easily implement a date class with all the necessary getters and setters.
The source code of the open source library can be viewed here at this link .
The first approach to implementing such classes is based on the use of C structures. As a drawback of this approach, it is that all fields are writable and readable, which is not always good.
struct person {
int id;
human type;
std::string name;
std::string address[5];
bool merried;
};
The second approach is based on hiding all fields and providing getters and setters for the fields. This approach is vividly used in the Java language. As an advantage, we can control the access to fields. The disadvantages include the fact that the class becomes large, and getters and setters do not carry a logical burden.
class person {
public:
void set_id(int id) {
this->id = id;
}
int get_id() const {
return id;
}
void set_merried(bool merried) {
this->merried = merried;
}
bool is_merried() const {
return merried;
}
void set_type(human type) {
this->type = type;
}
human get_type() const {
return type;
}
void set_name(const std::string& name) {
this->name = name;
}
const std::string& get_name() const {
return name;
}
private:
int id;
human type;
std::string name;
std::string address[5];
bool merried;
};
If the field is a class type, sometimes you need to set the object by value, by lvalue-link, by rvalue-link. And also using const / volatile modifiers.
class person {
public:
void set_name(const std::string& name) {
this->name = name;
}
void set_name(std::string&& name) {
this->name = std::move(name);
}
const std::string& get_name() const {
return name;
}
private:
int id;
human type;
std::string name;
std::string address[5];
bool merried;
};
Many languages support properties as a language feature. Writing code becomes cleaner and more reliable. To simplify the writing of getters and setters, you can use macros to generate code.
#define SETTER_PRIM(type, name) \
void set_##name(type value) { \
this->name = value; \
}
#define GETTER_PRIM(type, name) \
type get_##name() const { \
return name; \
}
But using macros is dangerous. We may not correctly indicate the type (type) or a variable of the wrong type (name). In the best case, we get a runtime error when using getters and setters. In the worst case, the error will remain.
I wanted us to be able to generate getters and setters, but at the same time we could check the correctness of type (type), the correctness of the type with a variable (name) and that the types were equal. And this can be done starting with C ++ 11 using the type_traits standard library.
#define SETTER_PRIM(type, name) \
void set_##name(type value) { \
using T1 = type; \
using T2 = decltype(name); \
static_assert(std::is_fundamental::value, \
"only primitive types"); \
static_assert(std::is_fundamental::value, \
"variable must be primitive"); \
static_assert(std::is_same::value, \
"both types must be same"); \
this->name = value; \
}
#define GETTER_PRIM(type, name) \
type get_##name() const { \
using T1 = type; \
using T2 = decltype(name); \
static_assert(std::is_fundamental::value, \
"only primitive types"); \
static_assert(std::is_fundamental::value, \
"variable must be primitive"); \
static_assert(std::is_same::value, \
"both types must be same"); \
return name; \
}
Using this approach, you can implement getters and setters for all types of class fields.
- primitive types
- object types
- transfers
- array
- pointers
- links
All macros for getters and setters implemented in the form of a header-only library. By connecting only one header file, you can easily implement a date class with all the necessary getters and setters.
#include "property.hpp"
class person {
public:
person() = default;
~person() = default;
SETTER_PRIM(int, id);
SETTER_FLAG(bool, merried);
SETTER_ENUM(human, type);
SETTER_PTR(int, next);
SETTER_ARR(std::string, address, 3);
SETTER_OBJ_LR(std::string, name);
SETTER_OBJ_CLR(std::string, name);
SETTER_OBJ_RR(std::string, name);
GETTER_PRIM(int, id);
GETTER_FLAG(bool, merried);
GETTER_ENUM(human, type);
GETTER_OBJ_LR(std::string, name);
GETTER_OBJ_CLR(std::string, name);
GETTER_PTR(int, next);
GETTER_ARR(std::string, address);
private:
int id;
human type;
std::string name;
std::string address[5];
bool merried;
int* next;
};
The source code of the open source library can be viewed here at this link .