Search code examples
c++sfinae

c++ call c function if it does exist


I have some C++ code that is automatically generated to wrap some C code.

The C code has a predictable structure with the exception that it has/has not a certain function.

Since the C++ code is derived from a description that does not have this information. I would like to use the template processor to decide if this function can be called.

small example:

struct SomeStruct{
  int indicatorMember;
};
extern "C" void someFun(struct SomeStruct* somePointer){
}



void someCPPcode(){
  SomeStruct s;
  // do something

  someMechanismToCall_someFunIfExists(&s);

  // do something other
}

How does someMechanismToCall_someFunIfExists have to look like, so that someCPPcode can be compiled/run in cases there someFun does exist and if it does not exist?

Is this even possible?

It would also be possible to decide if this function exists, if a certain member is part of a structure. so, if indicatorMember does exist, the function also exists.


Solution

  • You might use overload with lower priority to solve your issue:

    // "C-Header"
    struct SomeStruct
    {
      int indicatorMember;
    };
    
    // Present or not
    extern "C" void someFun(struct SomeStruct* somePointer){
    
    }
    
    // Fallback
    void someFun(...) { /*Empty*/ }
    
    void someCPPcode()
    {
      SomeStruct s;
      // do something
    
      someFun(&s);
    
      // do something other
    }
    

    it would also be possible to decide if this function exists, if a certain member is part of a structure. so, if indicatorMember does exist, the function also exists.

    There are several ways to detect presence of member, such as use of std::experimental::is_detected.

    but outside template, you still have issue:

    decltype(auto) someFunIfExists([[maybe_unused]] SomeStruct* p)
    {
        if constexpr (has_someFunc<SomeStruct>::value) {
            return someFun(p); // Not discarded as you might expect -> Error
        }
    }
    

    as if constexpr (false) { static_assert(false); } is invalid).

    So you have to wrap the function inside template:

    template <typename T>
    decltype(auto) someFunIfExists([[maybe_unused]] T* p)
    {
        if constexpr (has_someFunc<T>::value) {
            return someFun(p);
        }
    }
    
    void someCPPcode(){
      SomeStruct s;
      // do something
    
      someFunIfExists(&s);
    
      // do something other
    }