如何检查给定类型的变量是否可以解除引用?

问题描述 投票:0回答:2

有没有办法在C ++中确定变量的类型是指针还是任何带有重载的operator*的迭代器?

有标准的std::is_pointer,但它没有提到迭代器。

我想在这样的代码中使用它:

template<class T>
void func(T var)
{
    if constexpr (can_be_dereferenced<T>::value)
    {
        // do something with *var;
    }
}
c++ typetraits
2个回答
3
投票

你基本上想检查*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
投票

您可以使用编译时函数重载决策和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.
  [..]
© www.soinside.com 2019 - 2024. All rights reserved.