<commit_before>#pragma once

#include <QtCore/QString>
#include <QtCore/QMetaObject>

namespace interpreterBase {
namespace robotModel {

/// Describes a type of a pluggable device, not a concrete instance of it.
/// Given a set of PluggableDeviceInfo corresponding to some pluggable devices
/// hierarchy original inheritance relations can be recovered with isA() method.
class PluggableDeviceInfo
{
public:
	/// Creates a new instance of a PluggableDevice descriptor. The resulting object will
	/// correspond to a given type only if Q_OBJECT macro is used inside its declaration.
	template<typename T>
	static PluggableDeviceInfo create(QString const &friendlyName = QString())
	{
		// This line performs Q_OBJECT macro checking in the given type declaration.
		// Without Q_OBJECT macro incorrect metaObject will be passed and it will lead
		// to invalid isA() method work.
		static_assert(HasQObjectMacro<T>::Value,
				"No Q_OBJECT macro in the class that is passed into a template");
		return PluggableDeviceInfo(&T::staticMetaObject, friendlyName);
	}

	/// Returns if the device corresponding to 'this' inherits a 'parent' one or they are the devices of the same type.
	bool isA(PluggableDeviceInfo const &parent) const;

	/// Returns a string that can be displayed to a user as the name of the pluggable device.
	QString friendlyName() const;

private:
	/// Trait that tells if the Object has a Q_OBJECT macro.
	template <typename Object>
	struct HasQObjectMacro {
		template <typename T>
		static char test(int (T::*)(QMetaObject::Call, int, void **));
		static int test(int (Object::*)(QMetaObject::Call, int, void **));
		enum { Value = sizeof(test(&Object::qt_metacall)) == sizeof(int) };
	};

	friend bool operator ==(PluggableDeviceInfo const &device1, PluggableDeviceInfo const &device2);
	friend bool operator !=(PluggableDeviceInfo const &device1, PluggableDeviceInfo const &device2);

	explicit PluggableDeviceInfo(QMetaObject const *deviceType, QString const &friendlyName);

	QMetaObject const *mDeviceType;
	QString mFriendlyName;
};

inline bool operator ==(PluggableDeviceInfo const &device1, PluggableDeviceInfo const &device2)
{
	return QString(device1.mDeviceType->className()) == QString(device2.mDeviceType->className());
}

inline bool operator !=(PluggableDeviceInfo const &device1, PluggableDeviceInfo const &device2)
{
	return !(device1 == device2);
}

}
}<commit_msg>Added some explanations to Q_OBJECT checking mechanism<commit_after>#pragma once

#include <QtCore/QString>
#include <QtCore/QMetaObject>

namespace interpreterBase {
namespace robotModel {

/// Describes a type of a pluggable device, not a concrete instance of it.
/// Given a set of PluggableDeviceInfo corresponding to some pluggable devices
/// hierarchy original inheritance relations can be recovered with isA() method.
class PluggableDeviceInfo
{
public:
	/// Creates a new instance of a PluggableDevice descriptor. The resulting object will
	/// correspond to a given type only if Q_OBJECT macro is used inside its declaration.
	template<typename T>
	static PluggableDeviceInfo create(QString const &friendlyName = QString())
	{
		// This line performs Q_OBJECT macro checking in the given type declaration.
		// Without Q_OBJECT macro incorrect metaObject will be passed and it will lead
		// to invalid isA() method work.
		static_assert(HasQObjectMacro<T>::Value,
				"No Q_OBJECT macro in the class that is passed into a template");
		return PluggableDeviceInfo(&T::staticMetaObject, friendlyName);
	}

	/// Returns if the device corresponding to 'this' inherits a 'parent' one or they are the devices of the same type.
	bool isA(PluggableDeviceInfo const &parent) const;

	/// Returns a string that can be displayed to a user as the name of the pluggable device.
	QString friendlyName() const;

private:
	/// Trait that tells if the Object has a Q_OBJECT macro.
	template <typename Object>
	struct HasQObjectMacro
	{
		// Following two overloads will return int if qt_metacall function (generated by Q_OBJECT macro)
		// belongs to 'Object' type (and so Q_OBJECT macro is placed there) and char otherwise.
		template <typename T>
		static char returnIntIfHasQObjectMacro(int (T::*)(QMetaObject::Call, int, void **));
		static int returnIntIfHasQObjectMacro(int (Object::*)(QMetaObject::Call, int, void **));

		// Enum is used for forcing compiller evaluating below expression on compile-time
		enum { Value = sizeof(returnIntIfHasQObjectMacro(&Object::qt_metacall)) == sizeof(int) };
	};

	friend bool operator ==(PluggableDeviceInfo const &device1, PluggableDeviceInfo const &device2);
	friend bool operator !=(PluggableDeviceInfo const &device1, PluggableDeviceInfo const &device2);

	explicit PluggableDeviceInfo(QMetaObject const *deviceType, QString const &friendlyName);

	QMetaObject const *mDeviceType;
	QString mFriendlyName;
};

inline bool operator ==(PluggableDeviceInfo const &device1, PluggableDeviceInfo const &device2)
{
	return QString(device1.mDeviceType->className()) == QString(device2.mDeviceType->className());
}

inline bool operator !=(PluggableDeviceInfo const &device1, PluggableDeviceInfo const &device2)
{
	return !(device1 == device2);
}

}
}
{'fraction_non_alphanumeric': 0.08866615265998458, 'fraction_numerical': 0.004626060138781804, 'mean_word_length': 5.133569739952718, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5941404', 'n_tokens_mistral': 1499, 'n_tokens_neox': 1455, 'n_words': 560}