I attempted the following approach using c++ SFINAE and std::declval to find if there exists the proper method in a base class, that can be called from the derived class. The derived class gets the base class from a template parameter. This works for a public method in the base class but not a protected method. Ideally I would prefer to keep the method I'm checking for protected. Here is the simplified code
template <class Base>
class Derived : public Base {
// SFINAE tester to find existence of foo (only works with public foo methods)
template <class Type>
static auto test_foo(int) -> decltype(std::declval<Type>().foo(std::declval<Bar&>()), std::true_ type());
template <class>
static auto test_foo(...) -> std::false_type;
using has_foo = decltype(test_foo<Base>(0));
// using the has_foo constexpr
void process_bar(Bar& bar) {
if constexpr (has_foo{})
Base::foo(bar);
...
}
};
Is there a way to transform this so that it can access the protected member of the base class while using declval (I think using std::declval<Base> might be making it so that it doesn't have access to the protected members of Base despite inheriting from it). Any help is appreciated, thanks!
If I understand correctly, you want to check the existence of a foo() method receiving a Bar object.
You can try inheriting from the Base template class and from another class (With_foo, in the following example) with a public foo() method. In case of collision, also the Base class has a foo() method (private, protected or public), otherwise only the With_foo class has the method.
Should be enough the following class
template <typename Base>
class Check_foo {
private:
struct With_foo
{ void foo (Bar &) { } };
template <typename T>
struct Derived : public With_foo, T
{ };
template <typename T,
typename = decltype(std::declval<T>().foo(std::declval<Bar&>()))>
static auto test_foo (int) -> std::false_type;
template <typename...>
static auto test_foo (long) -> std::true_type;
public:
static constexpr bool value = decltype(test_foo<Derived<Base>>(0))::value;
};
The following is a full compiling example
#include <type_traits>
struct Bar
{ };
class Base_1
{ public: void foo (Bar &) { } };
class Base_2
{ protected: void foo (Bar &) { } };
class Base_3
{ private: void foo (Bar &) { } };
class Base_4
{ };
template <typename Base>
class Check_foo {
private:
struct With_foo
{ void foo (Bar &) { } };
template <typename T>
struct Derived : public With_foo, T
{ };
template <typename T,
typename = decltype(std::declval<T>().foo(std::declval<Bar&>()))>
static auto test_foo (int) -> std::false_type;
template <typename...>
static auto test_foo (long) -> std::true_type;
public:
static constexpr bool value = decltype(test_foo<Derived<Base>>(0))::value;
};
int main ()
{
static_assert( Check_foo<Base_1>::value);
static_assert( Check_foo<Base_2>::value);
static_assert( Check_foo<Base_3>::value);
static_assert(not Check_foo<Base_4>::value);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With