Ternary conditional operator will yield an lvalue, if the type of its second and third operands is an lvalue.
You can use the function template is_lvalue
(below) to find out if an operand is an lvalue and use it in the function template isTernaryAssignable
to find out if it can be assigned to.
A minimal example:
#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';
}
Output:
true
false
false
false
LIVE DEMO
Note: The operands you pass to isTernaryAssignable
are to be such that they will not undergo decay (For example an array which decays to pointer).