Как проверить, может ли быть разыменована переменная данного типа? - PullRequest
0 голосов
/ 27 марта 2019

Есть ли способ в C ++ определить, является ли тип переменной указателем или любым итератором с перегруженным operator*?

Существует стандартный std::is_pointer, но он ничего не говорит об итераторах.

Я хочу использовать его в таком коде:

template<class T>
void func(T var)
{
    if constexpr (can_be_dereferenced<T>::value)
    {
        // do something with *var;
    }
}

Ответы [ 2 ]

3 голосов
/ 27 марта 2019

Вы хотите проверить, действительно ли *var. Это идеальный вариант использования для проверки SFINAE:

#include <type_traits>
#include <utility>

namespace detail {
    // If `*(object of type T)` is valid, this is selected and
    // the return type is `std::true_type`
    template<class T>
    decltype(static_cast<void>(*std::declval<T>()), std::true_type{})
    can_be_dereferenced_impl(int);

    // Otherwise the less specific function is selected,
    // and the return type is `std::false_type`
    template<class>
    std::false_type can_be_dereferenced_impl(...);
}

template<class T>
struct can_be_dereferenced : decltype(detail::can_be_dereferenced_impl<T>(0)) {};

template<class T>
void func(T var)
{
    if constexpr (can_be_dereferenced<T&>::value)
    // Or         can_be_dereferenced<decltype((var))>::value
    {
        auto&& dereferenced = *var;
        // Use dereferenced
    }
}
0 голосов
/ 27 марта 2019

Вы можете сделать это таким образом, используя разрешение перегрузки функции времени компиляции и SFINAE:

template<class T, typename = std::enable_if_t<std::is_pointer<T>::value>>
void func(T var)
{
  // a pointer
}

template<class T, typename = std::enable_if_t<!std::is_pointer<T>::value>,
         typename = T::value_type>
void func(T var)
{
  // possibly an iterator
}

int main()
{
  int *i = new int(11);
  func(i); // Calls the first overload

  std::vector<int> v;
  std::vector<int>::const_iterator it = v.begin();

  func(it); // Calls the second overload

  func(2); // Fail, as there is no function for this argument.
  [..]
...