Однако, когда я пытаюсь упростить код, пытаясь удалить то, что я считаю ненужным
К сожалению (если я правильно понимаю) вы удалили что-то необходимое
Если я правильно понимаю, вы упростили следующие методы
template<typename U=T,
typename std::enable_if_t<std::is_same_v<U,T>>* = nullptr,
typename std::enable_if_t<!std::is_pointer_v<U>>* = nullptr>
inline T& at(i32 i)
{
return e[i];
}
template<typename U = T,
typename std::enable_if_t<std::is_same_v<U, T>>* = nullptr,
typename std::enable_if_t<std::is_pointer_v<U>>* = nullptr>
inline typename std::remove_pointer_t<T>& at(i32 i)
{
return *e[i];
}
следующим образом
template<typename std::enable_if_t<!std::is_pointer_v<T>>* = nullptr>
inline T& at(i32 i)
{
return e[i];
}
template<typename std::enable_if_t<std::is_pointer_v<T>>* = nullptr>
inline typename std::remove_pointer<T>::type& at(i32 i)
{
return *e[i];
}
К сожалению, SFINAE работает с шаблонным методом только тогда, когда используются тесты (std::enable_if_t
), основанные на шаблонных параметрах самого метода.
Я имею в виду: SFINAE не работает, когда в std::enable_if_t
тестах задействовано T
(и только T
), потому что T
является параметром шаблона структуры, а не параметром шаблона метода.
Так что вам нужно трюк
typename U = T
, которые "преобразуют" тип T
в параметр шаблона метода.
Вы можете немного упростить удаление typename
до std::enable_if_t
, потому что "_t
" в точности равно typename
(см. Определение std::enable_if_t
)
Не по теме: я не языковой слой, но, насколько я знаю,
std::enable_if_t<std::is_same_v<U,T>>* = nullptr
не совсем законно; Я предлагаю переписать, используя int
вместо void *
std::enable_if_t<std::is_same_v<U,T>, int> = 0
или, может быть bool
std::enable_if_t<std::is_same_v<U,T>, bool> = true
или другие целочисленные типы
В заключение, я предлагаю переписать ваш at()
метод следующим образом
template <typename U = T,
std::enable_if_t<std::is_same_v<U, T>, int> = 0,
std::enable_if_t<!std::is_pointer_v<U>, int> = 0>
inline T& at(i32 i)
{
return e[i];
}
template<typename U = T,
std::enable_if_t<std::is_same_v<U, T>, int> = 0,
std::enable_if_t<std::is_pointer_v<U>, int> = 0>
inline typename std::remove_pointer_t<T>& at(i32 i)
{
return *e[i];
}