Это пересказ мой предыдущий пост, так как я изменил вопрос (так что он, вероятно, не был помечен как новый вопрос и был пропущен). Надеюсь, я тоже урежу это.
У меня были такие функции, как:
#include <cstddef>
#include <type_traits>
template < typename E, typename T >
inline constexpr
auto checked_slice( E &&, T &&t ) noexcept -> T &&
{ return static_cast<T &&>(t); }
template < typename E, typename T, std::size_t N, typename U, typename ...V >
inline constexpr
auto checked_slice( E &&e, T (&t)[N], U &&u, V &&...v )
-> typename remove_some_extents<T, sizeof...(V)>::type &
{
typedef typename std::remove_reference<U>::type u_type;
typedef typename std::common_type<u_type, std::size_t>::type cmp_type;
return ( u < u_type{} ) || ( static_cast<cmp_type>(u) >=
static_cast<cmp_type>(N) ) ? throw e : checked_slice( static_cast<E &&>(e),
t[static_cast<U &&>( u )], static_cast<V &&>(v)... );
}
где remove_some_extents
это пользовательский шаблон класса, который походит на вызов std::remove_extent
мета-функция заданное количество раз.
Когда я попытался запустить программу, я получил кучу ошибок, таких как: «неверная инициализация ссылки типа Whatever(&)[X][Y]
из выражения типа Whatever(*)[Y]
» (или же Whatever(&)[Z]
от Whatever*
). Мой обходной путь должен был преобразовать условное выражение в if
—else
пара (и удаление constexpr
).
Я пытаюсь выяснить, что не так, поэтому я изучаю раздел об условном операторе в стандарте C ++ (2011). Это раздел 5.16. Когда одним из двух возможных действий является команда броска (или void
выражением), тогда условное выражение имеет тип другого выражения, но к этому другому выражению применяются стандартные преобразования, в том числе массив-указатель. (Это в параграфе 2.) Я думаю, это то, что меня портит. Есть ли способ обойти это? Я думал, что возвращение ссылки на массив подавляет преобразование a-to-p. Почему это работает, когда превращается в if/else
?
Ваш анализ верен. Я подозреваю, что неvoid
операнд «распадается» (то есть выполняются обычные преобразования) в такой ситуации, чтобы имитировать то, что происходит, когда два операнда различаются по типам — в последнем случае чаще всего целое условное выражение является prvalue.
Одна ситуация, в которой мы точно знаем и категорию значения, и тип условного выражения, — это когда два операнда являются точными совпадениями, поэтому мы можем использовать это в наших интересах:
cond ? (throw e, t) : t
будет lvalue ссылочного типа массива. (Конечно, последний операнд не должен быть буквально t
— Вы можете подключить свой рекурсивный вызов здесь просто отлично.)
Вы не сталкивались с таким препятствием при использовании if
/else
потому что в качестве утверждения язык не должен указывать общий тип и категорию значений для него.
Других решений пока нет …