mbed_dev
mbed_dev

Reputation: 1470

Evaluate whether class has derived templated-member function from CRTP-Base

Following scenario:

template <typename Derived>
    class TBase
{
    public:
        TBase() = default;
        ~TBase() = default;

        bool foo() noexcept
        {
            static_assert(&Derived::foo != &TBase<Derived>::foo, "foo missing in derived class.");
            return false; // dead-line
        }

        template <typename Bla>
        bool bar(Bla bla) noexcept
        {
            static_assert(&Derived::bar!= &TBase<Derived>::bar, "foo missing in derived class.");
            return false; // dead-line
        }
};



class TDerived : public TBase<TDerived>
    {
    public:

        TDerived () noexcept = default;
        ~TDerived () noexcept = default;

        bool foo() noexcept
        {
            // do something
            return false;
        }

        // bool bar(Bla bla) noexcept -> is not implemented
    };

int main()
{
    TDerived drvd;
    drvd.bar(2);
    return 0;
}

https://onlinegdb.com/BkU4IrTBL

I get the compiler-error (probably the compiler being not able to deduce the type):

Severity Code Description Project File Line Suppression State Error C2568 '!=': unable to resolve function overload

what I could do is deleting

template <typename PODType> bool protectData(PODType f_buf) noexcept = delete;

but I would like to - if possible - I would prefer the approach with the static_assert. How can I achieve this?

Upvotes: 0

Views: 57

Answers (1)

AVH
AVH

Reputation: 11516

The problem is that bar is never a function, it's a function template. If I change the problematic line a little, the static_assert works:

template <typename T>
bool bar(T obj) noexcept {
  static_assert(&Derived::bar != &TBase<Derived>::template bar<T>,
    "bar missing in derived class.");
  return false; // dead-line
}

However, that assertion will always fail, since it's explicitly comparing a "regular" function to the function template.

I got it to work by explicitly disambiguating the function pointers using static_cast:

template <typename T>
bool bar (T obj) noexcept {
  static_assert(
      static_cast<bool (Derived::*)(T)>(&Derived::bar)
        != static_cast<bool (TBase<Derived>::*)(T)>(&TBase<Derived>::bar)
    , "bar missing in derived class.");
  return false; // dead-line
}

However, you also explicitly need to pull in the templated bar function from TBase in TDerived:

class TDerived : public TBase<TDerived> { 
  public:
    using TBase<TDerived>::bar;
};

Upvotes: 1

Related Questions