2

I am trying to write a function, let's call it Base, which takes Derived as a template parameter and is also the base class of Derived, which defines a method if a certain method in Derived is defined.

Here is how I've attempted to implement this (derived from response to this question: How to let a base method be defined only if the derived class does not define a method of the same name)

#include <utility>

struct GetValueImpl
{
    template <typename T>
    static auto test(int) -> decltype(
        std::declval<T&>().GetValue(0),
        std::true_type{});
    template <typename...>
    static std::false_type test(...);
};
template <typename T>
struct GetValueDefined : public decltype(GetValueImpl::test<T>(0)) {};

template <typename Derived, int X>
class Base
{
    public:

    // I want to define this function only if GetValue is defined in Derived
    template <typename... Args>
    auto Test(const Args&...) -> typename std::enable_if<GetValueDefined<Derived>::value>::type
    {
    }
};

template <std::int32_t val>
class DerivedExample : public Base<DerivedExample<val>, 1>
{
    public:
    template <typename T>
    int GetValue() {return 0;}
};

int main() {
    DerivedExample<1> d;
    d.Test(1, 2);
    return 0;
}

This produces the following compiler error:

prog.cpp:21:10: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
     auto Test(const Args&...) -> typename std::enable_if<GetValueDefined<Derived>::value>::type
          ^
prog.cpp: In function ‘int main()’:
prog.cpp:36:7: error: ‘class DerivedExample<1>’ has no member named ‘Test’
     d.Test(1, 2);
       ^

working example here.

Clearly my std::enable_if check is failing. But why?

Community
  • 1
  • 1
quant
  • 21,507
  • 32
  • 115
  • 211
  • 2
    Having a base class depend on the behavior of a child class is a design smell, IMO. – Some programmer dude Aug 01 '14 at 02:18
  • 1
    @JoachimPileborg I don't disagree :) This is more of an exercise, I'm actually trying to do the inverse (see the linked question) but in trying to diagnose a related problem I tried switching the logic to create the function *if* the derived function exists, and I couldn't do it, so I posted this. – quant Aug 01 '14 at 02:19
  • You check for validity of `t.GetValue(0)` (with param) which is not provided by `DerivedExample`... – Jarod42 Aug 01 '14 at 02:58

2 Answers2

1

The SFINAE mechanism has to rely on names from the current template. Use a default argument for Derived so a (un)sucessful substitution can occur:

template <typename D = Derived, typename... Args>
auto Test(const Args&...) -> typename std::enable_if<GetValueDefined<D>::value>::type
{
}
David G
  • 94,763
  • 41
  • 167
  • 253
  • @Arman: After changing some code to have `GetValueDefined::value == true`, it compiles (http://ideone.com/GyfTTd) – Jarod42 Aug 01 '14 at 09:43
0

I am not sure if this will be of any help but you should look into the pre-proccessor commands like

#ifndef // if the class is not defined
#define // defines class
#endif  // ends if statement

For Example

#include "whatever.h" 
#ifndef CLASS_H 
#define CLASS_H
class base
{
 public:
 base(){}
 ~base(){}
 private:
 };
 #endif