Оцените, получил ли класс функцию шаблонного члена из CRTP-Base - PullRequest
0 голосов
/ 16 марта 2020

Следующий сценарий:

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

Я получаю ошибку компилятора (возможно, компилятор не может определить тип):

Код серьезности Описание Ошибка состояния подавления строки файла проекта C2568 '! =': Невозможно разрешить перегрузку функции

, что я могу сделать, это удалить

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

но я хотел бы - если это возможно - я бы предпочел подход с static_assert. Как мне этого добиться?

1 Ответ

1 голос
/ 17 марта 2020

Проблема в том, что bar никогда не является функцией, это шаблон функции. Если я немного изменю строку проблемной c, static_assert сработает:

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
}

Однако это утверждение всегда будет неудачным, поскольку оно явно сравнивает «обычную» функцию с шаблоном функции.

Я заставил его работать, явно устраняя неоднозначность указателей на функции, используя 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
}

Однако вам также явно необходимо извлечь шаблонную функцию bar из TBase в TDerived:

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