Создание оператора "?." из с# в c++
Пытаюсь интереса ради создать такое чудо.
При его использовании, если объект произвольного класса, к которому обращаются равен NULL, то строка не выполняется далее, иначе происходит обращение к полю/методу объекта.
При использовании с нетипизированными указателями встретился с проблемой невозможности обращения к методу. Т.к. Возвращается нетипизированный указатель, а приведение к типу не решило проблему.
По идее должен быть возврат ссылки объекта из кастомного оператора.
Как можно реализовать возвращение ссылки произвольного класса?
#define define const struct
#define operator(ReturnType, OperatorName, FirstOperandType, SecondOperandType) OperatorName ## _ {} OperatorName; template <typename T> struct OperatorName ## Proxy{public:OperatorName ## Proxy(const T& t) : t_(t){}const T& t_;static ReturnType _ ## OperatorName ## _(const FirstOperandType a, const SecondOperandType b);};template <typename T> OperatorName ## Proxy<T> operator<(const T& lhs, const OperatorName ## _& rhs){return OperatorName ## Proxy<T>(lhs);}ReturnType operator>(const OperatorName ## Proxy<FirstOperandType>& lhs, const SecondOperandType& rhs){return OperatorName ## Proxy<FirstOperandType>::_ ## OperatorName ## _(lhs.t_, rhs);}template <typename T> inline ReturnType OperatorName ## Proxy<T>::_ ## OperatorName ## _(const FirstOperandType a, const SecondOperandType b)
define operator(const void*, isNotNULL, const void*, const void*)
{
if(a != NULL)
return a;
}
#define isNotNULL <isNotNULL>
class dataBase
{
private:
int i = 10;
public:
int getI() {return i;}
};
int main()
{
dataBase db;
db isNotNULL .count()
return 0;
}
Ответы (2 шт):
Пока это лучшее, что у меня получилось: https://godbolt.org/z/WWdEXD
#include <iostream>
using namespace std;
struct smth
{
void go() { cout << "go" << endl; }
int ret(int x) { return x; }
} a;
smth *f(bool null)
{
cout << "f" << endl;
return null ? 0 : &a;
}
#define NN(p, op) [&](auto x) \
{ \
if constexpr (is_void_v<decltype(x->op)>) { if (x) return x->op; } \
else return x ? x->op : decltype(x->op){}; \
}(p)
int main()
{
int i = 10;
cout << "=== NONNULL ===" << endl;
NN(f(false), go());
cout << NN(f(false), ret(i)) + 7 << endl;
cout << "=== NULL ===" << endl;
NN(f(true), go());
cout << NN(f(true), ret(i)) + 7 << endl;
return 0;
}
PS: Хотелось записать покрасивее, но пока не вышло. Если ответят, обновлю.
Сразу стоит отметить, что в C# все ссылочные типы, то бишь ссылки на объекты любого класса, могут быть null, а все прочие - активно оборачиваться в Nullable<T>, в то время как в С++ такого не наблюдается. Вот в вашем примере db в принципе не может быть null. В качестве ближайшей альтернативы указатели могут иметь значение nullptr, а прочие типы можно оборачивать в std::optional. Тогда аналог оператора ?. будет выглядеть примерно так:
#include <string>
#include <optional>
int main()
{
::std::string * optional_p_text{};
// без возвращения значения
optional_p_text && (static_cast< void >(optional_p_text->length()), true);
// с возвращением значения
auto optional_result
{
optional_p_text
?
::std::optional< decltype(optional_p_text->length()) >{optional_p_text->length()}
:
::std::optional< decltype(optional_p_text->length()) >{}
};
return 0;
}