Search code examples
c++c++11boostsfinaetype-traits

C++11 std equivalent of Boost has_dereference


Many of Boost's SFINAE helpers have appeared in the std library with C++11, but has_dereference doesn't seem to have. Other than this feature, I've managed to eliminate a Boost dependency from my package, and I'd like to get rid of it entirely, so how best to get the same effect using just C++11 std features?


Solution

  • The easiest way to check if a class has some function with no external dependencies is generally with the void_t idiom.

    // Define this once in your project somewhere accessible
    template <class ... T>
    using void_t = void;
    

    The trick then is always the same; you define a class template that inherits from std::false_type:

    template <class T, class = void>
    struct has_dereference : std::false_type {};
    

    This is the "fallback" class template. Now we're going to define a specialization that only works when the type has the property we want:

    template <class T>
    struct has_dereference<T, void_t<decltype(*std::declval<T>())>> : std::true_type {};
    

    To use, just do:

    bool x = has_dereference<int*>::value;
    bool y = has_dereference<int>::value;
    

    etc.

    I will add that technically, operator* is actually a family of functions; the operator can be both CV qualified and value category qualified. Whenever you perform detection on a type, you are actually doing detection within this family. I won't get more into details because it's rarely encountered in practice (operator* is rarely value category qualified, and the operator almost always has a const version, and volatile rarely comes up) but it's worth being aware of in case you see something surprising.

    This technique is worth knowing about, especially if you are doing meta-programming without dependencies like Boost or Hana. You can read more about void_t here: How does `void_t` work.