如何检查给定类型的变量是否可以取消引用?
How to check whether variable of given type can be dereferenced?
在 C++ 中有没有办法确定变量类型是指针还是任何重载的迭代器operator*
?
有标准的 std::is_pointer
,但它只字不提迭代器。
我想在这样的代码中使用它:
template<class T>
void func(T var)
{
if constexpr (can_be_dereferenced<T>::value)
{
// do something with *var;
}
}
您可以使用编译时函数重载解析和 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.
[..]
您主要想检查 *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
}
}
在 C++ 中有没有办法确定变量类型是指针还是任何重载的迭代器operator*
?
有标准的 std::is_pointer
,但它只字不提迭代器。
我想在这样的代码中使用它:
template<class T>
void func(T var)
{
if constexpr (can_be_dereferenced<T>::value)
{
// do something with *var;
}
}
您可以使用编译时函数重载解析和 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.
[..]
您主要想检查 *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
}
}