| Home | Libraries | People | FAQ | More

### has_dereference

    template <class Rhs, class Ret=dont_care>
    struct has_dereference : public true_type-or-false_type {};

Inherits: If (i) `rhs` of type `Rhs` can be used in expression `*rhs`, and (ii) `Ret=dont_care` or the result of expression `*rhs` is convertible to `Ret` then inherits from true_type, otherwise inherits from false_type.

The default behaviour (`Ret=dont_care`) is to not check for the return value of prefix `operator*`. If `Ret` is different from the default `dont_care` type, the return value is checked to be convertible to `Ret`. Convertible to `Ret` means that the return value of the operator can be used as argument to a function expecting `Ret`:

    void f(Ret);
    Rhs rhs;
    f(*rhs); // is valid if has_dereference<Rhs, Ret>::value==true

If `Ret=void`, the return type is checked to be exactly `void`.

Header: `#include <boost/type_traits/has_dereference.hpp>` or `#include <boost/type_traits/has_operator.hpp>` or `#include <boost/type_traits.hpp>`

Compiler Compatibility: Requires working SFINAE (i.e. BOOST_NO_SFINAE is not set). Only a minority of rather old compilers do not support this.

Examples:

> `has_dereference<Rhs, Ret>::value_type` is the type `bool`.

> `has_dereference<Rhs, Ret>::value` is a `bool` integral constant expression.

> `has_dereference<int*>::value` is a `bool` integral constant expression that evaluates to `true`.

> `has_dereference<long*>` inherits from `true_type`.

> `has_dereference<int*, int>` inherits from `true_type`.

> `has_dereference<int*, const int>` inherits from `true_type`.

> `has_dereference<int const *>` inherits from `true_type`.

> `has_dereference<int * const>` inherits from `true_type`.

> `has_dereference<int const * const>` inherits from `true_type`.

> `has_dereference<int>` inherits from `false_type`.

> `has_dereference<double>` inherits from `false_type`.

> `has_dereference<void*>` inherits from `false_type`.

> `has_dereference<const int*, int&>` inherits from `false_type`.

See also: Operator Type Traits

Known issues:

- This trait cannot detect whether prefix `operator*` is public or not: if `operator*` is defined as a private member of `Rhs` then instantiating `has_dereference<Rhs>` will produce a compiler error. For this reason `has_dereference` cannot be used to determine whether a type has a public `operator*` or not.

      struct A { private: void operator*(); };
      boost::has_dereference<A>::value; // error: A::operator*() is private

- There is an issue if the operator exists only for type `A` and `B` is convertible to `A`. In this case, the compiler will report an ambiguous overload.

      struct A { };
      void operator*(const A&);
      struct B { operator A(); };
      boost::has_dereference<A>::value; // this is fine
      boost::has_dereference<B>::value; // error: ambiguous overload

- There is an issue when applying this trait to template classes. If `operator*` is defined but does not bind for a given template type, it is still detected by the trait which returns `true` instead of `false`. Example:

      #include <boost/type_traits/has_dereference.hpp>
      #include <iostream>

      template <class T>
      struct contains { T data; };

      template <class T>
      bool operator*(const contains<T> &rhs) {
      	return f(rhs.data);
      }

      class bad { };
      class good { };
      bool f(const good&) { }

      int main() {
      	std::cout<<std::boolalpha;
      	// works fine for contains<good>
      	std::cout<<boost::has_dereference< contains< good > >::value<<'\n'; // true
      	contains<good> g;
      	*g; // ok
      	// does not work for contains<bad>
      	std::cout<<boost::has_dereference< contains< bad > >::value<<'\n'; // true, should be false
      	contains<bad> b;
      	*b; // compile time error
      	return 0;
      }

- `volatile` qualifier is not properly handled and would lead to undefined behavior