Существует ли эквивалент С++ для оператора С# null коалесценции? Я делаю слишком много нулевых проверок в моем коде. Так что искал способ уменьшить количество нулевого кода.
С# нулевой коалесцирующий оператор-эквивалент для С++
Ответ 1
В С++ нет способа сделать это по умолчанию, но вы можете написать одно:
в С# оператор определяется как
a ?? b === (a != null ? a : b)
Итак, метод С++ будет выглядеть как
Coalesce(a, b) // put your own types in, or make a template
{
return a != null ? a : b;
}
Ответ 2
Я только что нашел это: The?? Оператор, известный как Нулевой оператор слияния
Вы также имеете его в C/C++ как расширение GNU, используя
?:
оператор:string pageTitle = getTitle() ?: "Default Title";
Ответ 3
Использование шаблонов и С++ 11 lambdas. Первый аргумент (левая часть) оценивается только один раз. Второй аргумент (правая сторона) оценивается только в том случае, если первый является ложным (обратите внимание, что "if" и "?" Статически передают предоставленное выражение в bool и что указатели имеют "явный оператор bool() const", который является равным to '!= nullptr')
template<typename TValue, typename TSpareEvaluator>
TValue
coalesce(TValue mainValue, TSpareEvaluator evaluateSpare) {
return mainValue ? mainValue : evaluateSpare();
}
Пример использования
void * const nonZeroPtr = reinterpret_cast<void *>(0xF);
void * const otherNonZeroPtr = reinterpret_cast<void *>(0xA);
std::cout << coalesce(nonZeroPtr, [&] () { std::cout << "Never called"; return otherNonZeroPtr; }) << "\n";
Будет просто печатать '0xf' в консоли. Чтобы написать лямбда для rhs, есть немного шаблона
[&] () { return <rhs>; }
но это лучшее, что можно сделать, если у вас нет поддержки синтаксисом языка.
Ответ 4
Как насчет этого?
#define IFNULL(a,b) ((a) == null ? (b) : (a))
Ответ 5
Просто хочу расширить ответ @Samuel Garcia, обобщая шаблон и добавляя вспомогательные макросы, чтобы срубить лямбда-шаблон:
#include <utility>
namespace coalesce_impl
{
template<typename LHS, typename RHS>
auto coalesce(LHS lhs, RHS rhs) ->
typename std::remove_reference<decltype(lhs())>::type&&
{
auto&& initialValue = lhs();
if (initialValue)
return std::move(initialValue);
else
return std::move(rhs());
}
template<typename LHS, typename RHS, typename ...RHSs>
auto coalesce(LHS lhs, RHS rhs, RHSs ...rhss) ->
typename std::remove_reference<decltype(lhs())>::type&&
{
auto&& initialValue = lhs();
if (initialValue)
return std::move(initialValue);
else
return std::move(coalesce(rhs, rhss...));
}
}
#define COALESCE(x) (::coalesce_impl::coalesce([&](){ return ( x ); }))
#define OR_ELSE ); }, [&](){ return (
Используя макросы, вы можете просто:
int* f();
int* g();
int* h();
int* x = COALESCE( f() OR_ELSE g() OR_ELSE h() );
Надеюсь, это поможет.
Ответ 6
Существует расширение GNU GCC, позволяющее использовать оператор ?:
с отсутствующим средним операндом, см. Условия с пропущенными операндами.
Средний операнд в условном выражении может быть опущен. Тогда если первый операнд ненулевой, его значение является значением условное выражение.
Поэтому выражение
x ? : y
имеет значение
x
, если оно отлично от нуля; в противном случае значениеy
.Этот пример совершенно эквивалентен
x ? x : y
В этом простом случае возможность опустить средний операнд не особенно полезен. Когда это становится полезным, это когда первый операнд содержит или может (если это макрос-аргумент) содержать сторону эффект. Затем повторение операнда в середине будет выполнять побочный эффект в два раза. Пропуск среднего операнда уже использует значение вычисляется без нежелательных последствий его пересчета.
Это расширение также поддерживается clang. Тем не менее, перед использованием расширения вы должны уточнить у используемого вами компилятора и требования переносимости кода. Примечательно, что компиляторы MSVC C++ не поддерживают опущенные операнды в ?:
.
Смотрите также связанное обсуждение Кару здесь.