yan
yan

Reputation: 2982

How to check for operator != existence for template arguments with C++ 17?

I have the following use case:

template<typename T>
struct Foo
{
  bool setValue(T const &iValue)
  {
    if(fValue != iValue)
    {
      fValue = iValue;
      return true;
    }
    return false;
  }

  T fValue;
};

which works only as long as T provides a operator!= implementation (and I suppose one of the complication is that operator!= can be implemented as member function of T or not...).

Ideally I would like to write something like this using C++ 17 if constexpr syntax

template<typename T>
struct Foo
{
  bool setValue(T const &iValue)
  {
    if constexpr (is_diff_operator_defined<T>::value) {
      if(fValue != iValue)
      {
        fValue = iValue;
        return true;
      }
    } else {
        fValue = iValue;
        return true;
    }
    return false;
  }

  T fValue;
};

How would I go about it? Please note I am using C++ 17 so would prefer a solution that uses the latest and greatest feature (likes if constexpr which makes the code a lot easier to read/comprehend than optional dummy template function parameters we usually see with sfinae...)

Upvotes: 1

Views: 122

Answers (1)

Guillaume Racicot
Guillaume Racicot

Reputation: 41780

With the detection idiom it's quite simple to do:

template<typename T>
using operator_not_eq_t = decltype(std::declval<T const&>() != std::declval<T const&>());

template<typename T>
constexpr auto is_diff_operator_defined = is_detected_v<operator_not_eq_t, T>;

Then simply use it with if constexpr as you wrote. (minus ::value)

Note that with concepts you can simply do that inline:

if constexpr (requires { fValue != iValue; }) {
    if (fValue != iValue) {
        // ...
    }
}

Upvotes: 1

Related Questions