Home > Software design >  C type_traits / how can i not use parents member function with type_traits?
C type_traits / how can i not use parents member function with type_traits?

Time:09-26

When inheriting member functions of C class, how to use type_traits to prevent them from being used under certain conditions?

I want to get Error Message, when Class B call function of foo()! when i using category random_access_iterator_tag, i can use function ( foo() )

#include <iostream>
#include <type_traits>
#include <iterator>
#include <ranges>

template<typename Derived> class Base
{
    public:
      void foo() {}
      void goo() {}
    
};

class A : public Base<A>
{
public:
    using category = std::random_access_iterator_tag;
};

class B : public Base<B>
{
public:
    using category = std::bidirectional_iterator_tag;
};

int main()
{
    A a;
    B b;
    a.foo(); // OK
    a.goo(); // OK
    b.foo(); // I want to get Error ( Compile )
    b.goo(); // OK
    
}

CodePudding user response:

Mark foo in the base protected and then make it publicly available in the derived classes that should allow it to be used via using declaration:

template<typename Derived> class Base
{
    protected:
      void foo() {}
    public:
      void goo() {}
};

class A : public Base<A>
{
public:
    using category = std::random_access_iterator_tag;
    using Base::foo;
};

//...

CodePudding user response:

Within CRTP, Derived class is incomplete, so you cannot check for category.

If you create category traits outside, you might do:

template <typename T>
struct category;

template <typename T>
using category_t = typename category<T>::type;


template<typename Derived> class Base
{
public:
   void foo()
   requires(!std::is_same_v<category_t<Derived>, std::bidirectional_iterator_tag>)
   // Or more appropriate condition
   {}

   void goo() {}
};

template <>
struct category<class A>
{
    using type = std::random_access_iterator_tag;
};
class A : public Base<A> {};


template <>
struct category<class B>
{
    using type = std::bidirectional_iterator_tag;
};
class B : public Base<B> {};

int main()
{
    A a;
    B b;
    a.foo(); // OK
    a.goo(); // OK
    b.foo(); // KO as expected
    b.goo(); // OK
    
}

Demo

  • Related