cppreference.com says about is_assignable<T,U>
type-trait that:
If the expression
std::declval<T>() = std::declval<U>()
is well-formed in unevaluated context, provides the member constant value equal true. For any other type, value is false. The types T and U must be complete object types, cv void or arrays of unknown bound. Access checks are performed as if from a context unrelated to either type.
But code:
template< std::size_t ...indices, std::size_t ...counter >
auto
invert_indices(std::index_sequence< counter... >)
{
constexpr std::size_t size = sizeof...(counter);
constexpr std::size_t inverted[size]{indices...};
return std::index_sequence< inverted[size - 1 - counter]... >{};
}
template< std::size_t ...indices >
auto
invert_indices()
{
return invert_indices< indices... >(std::make_index_sequence< sizeof...(indices) >{});
}
template< std::size_t ...indices >
using make_inverted_indices_t = decltype(invert_indices< indices... >());
using L = make_inverted_indices_t< 10, 20, 30 >;
using R = std::index_sequence< 30, 20, 10 >;
static_assert(std::is_same< L, R >{});
static_assert(std::is_assignable< make_inverted_indices_t< 10, 20, 30 > &, R >{});
static_assert(!std::is_assignable< make_inverted_indices_t< 10, 20, 30 > &, int >{});
work, in spite of functions invert_indices
are not constexpr
and have result type auto
.
For context to be unevaluated is it still permittable to look into function bodies during decltype
working?
invert_indices< indices... >()
is not evaluated, but its return type is known. It requires to look at body to know its type because of theauto
return type.so
make_inverted_indices_t< 10, 20, 30 >
isstd::index_sequence< 30, 20, 10 >
which is a complete object type.