Тернарный условный оператор выдаст lvalue, если тип его второго и третьего операндов - lvalue.
Вы можете использовать шаблон функции is_lvalue
(ниже), чтобы выяснить, является ли операнд lvalue, и использовать его в шаблоне функции isTernaryAssignable
, чтобы узнать, можно ли ему присвоить.
Минимальный пример:
#include <iostream>
#include <type_traits>
template <typename T>
constexpr bool is_lvalue(T&&) {
return std::is_lvalue_reference<T>{};
}
template <typename T, typename U>
bool isTernaryAssignable(T&& t, U&& u)
{
return is_lvalue(std::forward<T>(t)) && is_lvalue(std::forward<U>(u));
}
int main(){
int i= 2,j =10 ;
((i < 3) ? i : j) = 7; //Ok
std::cout << std::boolalpha << isTernaryAssignable(i, j); std::cout << '\n';
std::cout << std::boolalpha << isTernaryAssignable(i, 10); std::cout << '\n';
std::cout << std::boolalpha << isTernaryAssignable(2, j); std::cout << '\n';
std::cout << std::boolalpha << isTernaryAssignable(2, 10); std::cout << '\n';
}
Выход:
true
false
false
false
LIVE DEMO
Примечание : Theоперанды, которые вы передаете isTernaryAssignable
, должны быть такими, чтобы они не подвергались распаду (например, массив, который распадается на указатель).