Создание оператора "?." из с# в 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 шт):

Автор решения: Qwertiy

Пока это лучшее, что у меня получилось: 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: Хотелось записать покрасивее, но пока не вышло. Если ответят, обновлю.

→ Ссылка
Автор решения: user7860670

Сразу стоит отметить, что в 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;
}

https://godbolt.org/z/Y5jBr6

→ Ссылка