.(dot) access to static method - c++

Following is a popular code:
class A
{
public:
static const string TYPE = "AEvent";
const string& getType() { return TYPE; }
};
Above code could be use like this:
if (aInstance.getType() == A::TYPE)
{
...
}
It's fine. But it's not intuitiveness. Did not? Look at the next code:
class A
{
public:
static const string& getType()
{
static const string TYPE = "AEvent";
return TYPE;
}
}
//Usage
if (aInstance.getType() == A::getType())
....
Of course, getType is static method but it's possible to access dot operator and It's more intuitively see to me.
How do you think about?

If it's clearer to use obj.static_member (or method), then use it; this is often true when the type name is long, such as with templates. Otherwise use Type::static_member.

As long as you're returning a static variable from static method it should be fine. It doesn't matter if you call it using dot or resolution operator. Either way it's part of the object as well as the class which should give you the same static variable.

Related

how does std::optional work under the hood?

I just learned about the std::optional feature in c++ 17 along with a few other very useful features...
but there is a few things that I don't understand about std::optional that I would like someone to explain them to me:
first of all as far as I know in std::optional the return value can either be the specified type or it can be nothing like this :
std::optional<std::string> getName()
{
if(person.hasName())
{
return person.name;
}
else
{
return {};
}
}
how does return {} returns nothing ? like for example if I was to make a similar class that return either the specified value or nothing, how do I make my own class so return {} is valid ? I'm I misunderstanding something here ?
my second question is that when you want to check the return value you can either do :
int main()
{
std::optional<std::string> name = getName();
if(name.has_value()) // check if the name is valid using the has_value function
{
...
}
}
or i can also do :
int main()
{
std::optional<std::string> name = getName();
if(name) // check if the name is valid only using the variable name ???
{
...
}
}
I'm really confused about this how could a variable name return a boolean ? not like the constructor of an object can return anything, so how is this possible ?
again let's say I want to make my own class that is kind of similar to std::optional how do I make it so an instance of my class can be used as a boolean ?
I would really appreciate answers that adress my questions and not something related to when to use std::optional or why I shouldn't make my own class that does the same thing etc...
thanks!
return {};
will simply call the default constructor of the class.
By giving the class a conversion operator to bool it can be implicitly converted to a bool when needed.
It would look something along the lines of
template <typename T>
class optional {
public:
optional() {}
optional(T t) : has_value(true), value(std::move(t)) {}
operator bool() {
return has_value;
}
private:
bool has_value = false;
T value;
}
Very simplified, missing assignement operators and more.
how do I make my own class so return {} is valid ?
By making the class default constructible. Exactly how to do that depends on the class. In cases where the class is implicitly default constructible you need to do nothing, while in other cases you may need to explicitly declare the constructor. Like this for example: ClassName() = default;.
how could a variable name return a boolean
Think about how this variable name "returns a boolean":
int x = 42;
if (x)
;
Or how this variable name "returns a std::string_view":
const char* str = "example";
std::string__view sv = str;
This is called a conversion from one type to another. That is what happens in if(name).
how do I make it so an instance of my class can be used as a boolean ?
By providing a conversion operator.

Call an "initialize" function in an object when one of its member functions are called

I am trying to implement lazy initializing in C++ and I am searching for a nice way to call the Initialize() member function when some other method like object->GetName() gets called.
Right now I have implemented it as follows:
class Person
{
protected:
bool initialized = false;
std::string name;
void Initialize()
{
name = "My name!"; // do heavy reading from database
initialized = true;
}
public:
std::string GetName()
{
if (!initialized) {
Initialize();
}
return name;
}
};
This does exactly what I need for the time being. But it is very tedious to setup the initialized check for every method, so I want to get rid of that. If someone knows a nice way in C++ to improve this above example, I would like to know!
Could maybe operators be used to achieve calling Initialize() when using -> for example?
Thanks!
Sounds like a job for templates! Create a lazily_initialized wrapper that takes a type T and a function object TInitializer type:
template <typename T, typename TInitializer>
class lazily_initialized : TInitializer
{// ^^^^^^^^^^^^^^
// inheritance used for empty-base optimization
private:
T _data;
bool _initialized = false;
public:
lazily_initialized(TInitializer init = {})
: TInitializer(std::move(init))
{
}
T& get()
{
if(!_initialized)
{
static_cast<TInitializer&>(*this)(_data);
_initialized = true;
}
return _data;
}
};
You can the use it as follows:
struct ReadFromDatabase
{
void operator()(std::string& target) const
{
std::cout << "initializing...\n";
target = "hello!";
}
};
struct Foo
{
lazily_initialized<std::string, ReadFromDatabase> _str;
};
Example:
int main()
{
Foo foo;
foo._str.get(); // prints "initializing...", returns "hello!"
foo._str.get(); // returns "hello!"
}
example on wandbox
As Jarod42 mentioned in the comments, std::optional<T> or boost::optional<T> should be used instead of a separate bool field in order to represent the "uninitialized state". This allows non default-constructible types to be used with lazily_initialized, and also makes the code more elegant and safer.
As the former requires C++17 and the latter requires boost, I used a separate bool field to make my answer as simple as possible. A real implementation should consider using optional, using noexcept where appropriate, and also consider exposing a const-qualified get() that returns a const T&.
Maybe call it in the constructor?
Edit: Uh, i missed the point of your question sorry.
What about a lazy factory initialization?
https://en.wikipedia.org/wiki/Lazy_initialization#C.2B.2B

How can I bundle additional information to an enum?

Let's say I have an enumeration of statuses for a game I'm working on. At first, I have something like this:
enum class Status {
OK, HURT, DYING, DEAD
};
That's all fine and dandy, but now I want to print the name of the status. Naturally, if this was a normal class, I would call getName() on an instance of Status. However, no such option exists for an enumeration.
A way to solve this problem is to have something like this:
const char * getName(Status status) {
switch(status) {
case Status::OK:
return "OK";
break;
/*and so on */
}
However, this is clearly not very extensible. It becomes a problem when you have a lot of enums with lots of data tied to them. You also don't really tie related data together in a very meaningful way. With uniform call syntax, you could get something close, like this:
Status::OK.getName();
But that's not standard yet.
Another way to solve this problem is through static const members inside a class, like so:
class Status {
std::string name;
Status(std::string name):name(std::move(name)) {}
public:
const std::string & getName() const { return name; }
static const Status OK, HURT, DYING, DEAD;
};
//in some .cpp
const Status Status::OK("OK"), Status::HURT("Hurt"), Status::DYING("Dying"), Status::DEAD("Dead");
That's all well and good, and it works out fine, for a while. But now, I want to write some code to deal with each Status, so instinctively I prefer a switch over an if-else chain.
I write this:
Status status = getStatus();
switch(status) {
case Status::OK:
//do something
default:
//do something else
}
Of course, this doesn't work. I need a converting operator! So I add that
operator int() { return /*some sort of unique value*/; }
And... still nothing. The reasoning is that the operator must be a constexpr. Which is obvious, knowing the detail of switch, but it doesn't really help. So the next logical step is to have the static consts become static constexprs.
class Status {
const char * name; //we are in constexpr land now
constexpr Status(const char * name):name(name) {}
public:
constexpr const char * getName() const { return name; }
constexpr operator int() const { return /*some sort of unique value*/; }
static constexpr Status OK = Status("OK"),
HURT = Status("Hurt"),
DYING = Status("Dying"),
DEAD = Status("Dead");
};
//in some .cpp
constexpr Status Status::OK, Status::HURT, Status::DYING, Status::DEAD;
The reason for having to put the statics is because constexpr have to be initialized on the spot. This would work fine, and honestly it covers all my needs. The only problem is that it doesn't compile. It makes sense: how can a class whose definition is not done yet be initialized? This is not a problem with the consts, because they are delayed in their instantiation.
So now, the only reasonable way to do something like that is through a another class, so that the size of Status is known when we create the constexprs.
class Status {
const char * name;
constexpr Status(const char * name):name(name) {}
public:
constexpr const char * getName() const { return name; }
constexpr operator int() const { return /*some sort of unique value*/; }
struct constants;
};
struct Status::constants {
static constexpr Status OK = Status("OK"),
HURT = Status("Hurt"),
DYING = Status("Dying"),
DEAD = Status("Dead");
};
//in some .cpp
constexpr Status Status::constants::OK, Status::constants::HURT, Status::constants::DYING, Status::constants::DEAD;
It's a distance away from the natural syntax of Status::NAME, instead having to say something like Status::constants::NAME. Another concern is the operator int(). There is no way (that I know of) to make this be populated in a way such as an enum would be. In a static const implementation, the obvious choice is to have a private static int, increment it in the ctor, and store it, using that as the return value of the conversion operator. However, this is no longer an option in the constexpr version. Maybe there's some sort of template magic to do it, and if so I'd love to see it. So my question is, are there any improvements to be done using modern C++ to the way we bundle information to an enum?
Based on Columbo's answer here: Is a class definition complete when it is passed to a base class?, it is possible to achieve expanded enums.
template<class T>
class Constants {
public:
static const T OK, HURT, DYING, DEAD;
};
template <typename T>
constexpr T Constants<T>::OK = T("OK");
template <typename T>
constexpr T Constants<T>::HURT = T("Hurt");
template <typename T>
constexpr T Constants<T>::DYING = T("Dying");
template <typename T>
constexpr T Constants<T>::DEAD = T("Dead");
class Status : public Constants<Status> {
friend class Constants<Status>;
const char * name;
constexpr Status(const char * name):name(name) {}
public:
constexpr const char * getName() const { return name; }
constexpr operator int() const { return /*some sort of unique value*/; }
};
While there are still some issues with this implementation, such as a lack of returning a unique value (probably have to just make the ctor take one and do it manually), it looks pretty good. Note however this won't compile on MSVC (due to lack of good constexpr support) or Clang (due to bug 24541). But hey, it's the best we've got so far.

Template substitution for function names

I'm using a third party C++ library which has a json parsing class that has
different functions like this:
GetInt
GetBool
GetString
GetDouble
I'd like to write a utility function that can access this class. I'm thinking of something like this:
class <template T>
class MyClass {
static T getValue(ThirdPartyClass someObj, const string &key) {
if(someObj[key].IsDouble())
return someObj[key].GetDouble();
else if (someObj[key].IsString())
return someObj[key].GetString();
// ... (for other types)
}
}
The caller of this class will hold the correct return type.
However this is ugly. Is there any way (using macro substitution for example) I can avoid the if conditions? The third party class has IsXXTypeXX and corresponding GetXXTypeXX functions (where XXTypeXX is Int, Double,String or Bool).
I know the return type when I call the function for eg:
int i = getValue(someObj, "intKey");
string s = getValue(someObj, "strKey");
So I dont need the if conditions at all. Ideally I would look to have something so
I would be able to do this:
int i = MyClass<int>::getValue(someObj, "intKey");
string s = MyClass<string>::getValue(someObj, "strKey");
Why not just write a bunch of static Get functions (GetInt/GetDouble...) that validates the input, returns the appropriate type result and throws an exception if it isn't that type?
Technically you can achieve the public interface that you've outlined there but that would involve very ugly looking template specialization.
It would probably be better if you just had a bunch of static functions instead. Here is what template specialization would look like:
template <typename T> class MyClass {
static T getValue(ThirdPartyClass someObj, const string &key) {
// handle types that you didn't specialize for
}
};
template <> class MyClass <string> {
static string getValue(ThirdPartyClass someObj, const string &key) {
return someObj[key].GetString();
}
};
template <> class MyClass <int> {
static int getValue(ThirdPartyClass someObj, const string &key) {
return someObj[key].GetInt();
}
};
//..
Skeleton key for software engineering: add an intermediate layer.
#include <string>
#include <cassert>
using std::string;
class Proxy {
public:
enum Type {
Int,
Bool,
String,
Double
};
Type type;
int i;
bool b;
string s;
double d;
operator int() const {
assert(type == Int);
return i;
}
operator bool() const {
assert(type == Bool);
return b;
}
operator string() const {
assert(type == String);
return s;
}
operator double() const {
assert(type == Double);
return d;
}
Proxy(int i) : type(Int), i(i) {}
Proxy(bool b) : type(Bool), b(b) {}
Proxy(string s) : type(String), s(s) {}
Proxy(double d) : type(Double), d(d) {}
}; // class Proxy
Proxy getValue(ThirdPartyClass someObj, const string &key) {
if (someObj[key].IsDouble())
return someObj[key].GetDouble();
else if (someObj[key].IsString())
return someObj[key].GetString();
//... (for other types)
}
int main() {
int i = getValue(someObj, "intKey"); // if type does not match, a exception will be thrown.
string s = getValue(someObj, "strKey");
}
The code you showed won't compile. You can't in the same function return a double, a string, and an int. What you'd have to do it specialize for each return type, and then call only the function for that type:
template <>
class MyClass<int> getValue(ThirdPartyClass someObj, const string& key) {
if(someOjb[key].IsInt()) return someObj[key].GetInt();
else { /* Maybe throw an exception */ }
};
and repeat for each type.
Now, you're probably thinking, "this is silly, how come I have to specialize each type?" That's because your JSON library is using type erasure, so you have to check the type at runtime. The only way to save yourself the work is if the library provides a templated get.
If you want, you could create a macro to stamp these instantiations out. It would take advantage of the # (stringification) and ## (concatenation) features of the preprocessor. It'll probably be clearer to just write them out.

Question regarding factory pattern

I have a factory class to build objects of base class B.
The object (D) that uses this factory receives a list of strings representing the actual types.
What is the correct implementation:
the factory receives an Enum (and uses switch inside the Create function) and D is responsible to convert the string to Enum.
the factory receives a string and checks for a match to a set of valid strings (using ifs')
other implementation i didn't think of.
I would separate the conversion of strings to enum into a distinct object. This can easily be solved by a map btw. But error handling etc. is still something which neither D nor the factory should be worried about.
Then either D calls the converter to get its enum, or it is already converted beforehand, so D only needs to pass the enum to the factory. (Btw the factory would better use a map too instead of a switch internally).
This raises the question: do you actually need the enums at all (in places other than D and the factory)? If not, maybe the enum could be left out of the picture and you could use a map to convert directly from strings to types (i.e. - since C++ doesn't support dynamic class loading - to function objects which create the necessary concrete type instances for you). A rough example (I don't have an IDE to test it so bear with me if there are any errors in it):
// Function type returning a pointer to B
typedef (B*)(*func)() StaticConstructor;
// Function creating instances of subclass E
B* createSubclassE() {
return new E(...);
}
// Function creating instances of subclass F
B* createSubclassF() {
return new F(...);
}
// Mapping from strings to constructor methods creating specific subclasses of B
map<string, StaticConstructor> factoryMap;
factoryMap["E"] = &createSubclassE;
factoryMap["F"] = &createSubclassF;
Of course, the created instances should also be disposed of properly - in production code, the returned objects could be e.g. enclosed in an auto_ptr. But I hope this short example is enough to show you the basic idea. Here is a tutorial if you want more...
You can put all matching strings in the set or list and check if it contains your strings instead of writing ifs/switches.
My project on VC++/Qt had a large number of XML files containing strings that had a Enum representation into the source.
So for each Enum we had a wrapper with overloaded operator QString <> Enum:
enum DataColumnTypeEnum
{
DataColumnTypeNotSet,
ColumnBinary,
ColumnBoolean,
ColumnDate,
ColumnDateTime,
ColumnNumber,
ColumnFloat,
ColumnPrimary,
ColumnString,
ColumnText,
};
class DataColumnType
{
public:
DataColumnType();
DataColumnType(DataColumnTypeEnum);
DataColumnType(const QString&);
DataColumnType& operator = (DataColumnTypeEnum);
DataColumnType& operator = (const QString&);
operator DataColumnTypeEnum() const;
operator QString() const;
private:
DataColumnTypeEnum type;
};
DataColumnType& DataColumnType::operator = (const QString& str)
{
str.toLower();
if(str.isEmpty()) type = DataColumnTypeNotSet;
else if(str == "binary") type = ColumnBinary;
else if(str == "bool") type = ColumnBoolean;
else if(str == "date") type = ColumnDate;
else if(str == "datetime") type = ColumnDateTime;
else if(str == "number") type = ColumnNumber;
else if(str == "float") type = ColumnFloat;
else if(str == "primary") type = ColumnPrimary;
else if(str == "string") type = ColumnString;
else if(str == "text") type = ColumnText;
return *this;
}
but the approach in last listing is very ugly.
Better to create a static hash table or dictionary and look up into.
The normal way is to have your factory as a singleton. Then each class based on class B registers it's create function and name with the factory at static initialisiation time. This is often done with macros. The factory then can creates a fast hash table of these name to create functions. Etc... you get the drift.
I personally use an enhanced enum because I've always found the enum of C++ lacking: messages like Type 3 - method -begin aren't much informative.
To this way, I use a simple templated class:
template <class Holder>
class Enum
{
public:
typedef typename Holder::type enum_type;
Enum(): mValue(Invalid()) {}
Enum(enum_type i): mValue(Get(i)) {}
explicit Enum(const std::string& s): mValue(Get(s)) {}
bool isValid() const { return mValue != Invalid(); }
enum_type getValue() const { return mValue->first; }
private:
typedef typename Holder::mapping_type mapping_type;
typedef typename mapping_type::const_iterator iterator;
static const mapping_type& Mapping() { static mapping_type MMap = Holder::Initialize(); return MMap; }
static iterator Invalid() { return Mapping().end(); }
static iterator Get(enum_type i) { // search }
static iterator Get(const std::string& s) { // search }
iterator mValue;
};
You define Holder like so:
struct Example
{
typedef enum {
Value1,
Value2,
Value3
} type;
typedef std::vector< std::pair< type, std::string > > mapping_type;
static mapping_type Initialize() {
return builder<mapping_type>()(Value1,"Value1")(Value2,"Value2")(Value3,"Value3");
}
};
You can define a macro for it:
DEFINE_ENUM(Example, (Value1)(Value2)(Value3))
But I let the implementation as an exercise (Boost.Preprocessor is your friend).
The cool thing is to use it!
int main(int argc, char* argv[])
{
std::string s;
std::cin >> s;
Enum<Example> e(s);
switch(e.getValue())
{
case Example::Value1:
case Example::Value2:
++e;
case Example::Value3:
std::cout << e << std::endl;
default:
}
}