Pranjal Kaler
Pranjal Kaler

Reputation: 493

How to check if a class has specific function to avoid compile time issues?

I have two class A and B, with a common function doing some operation on both of them with just a minor difference.

I tried using std::is_same, but looks like it won't prevent compile-time issues.

class A {
public: 
    void aSpecificFunctionToA() {
    }
};

class B {
};


template<typename T>
void someFunction(T obj) {
    if(std::is_same<T, A>::value)
    {
        obj.aSpecificFunctionToA();
    }
}

How to tackle this situation?

Upvotes: 1

Views: 147

Answers (4)

Marek R
Marek R

Reputation: 37657

I prefer simple old fashion solution:

#define LOG std::cout << __PRETTY_FUNCTION__ << '\n'

class A {
public: 
    void aSpecificFunctionToA() {
        LOG;
    }
};

class B {
};


template<typename T>
void someFunction(T obj) {
    LOG;
}

void someFunction(A obj) {
    LOG;
    obj.aSpecificFunctionToA();
}

https://godbolt.org/z/brPGr6

Upvotes: 0

Martin Morterol
Martin Morterol

Reputation: 2870

If you have more than one class having aSpecificFunctionToA (well, in this case the name is poorly choose) you can use SFINAE.

Full C++11 :

#include <vector>
#include <functional>
#include <iostream>
#include <memory>
#include <type_traits>

namespace detail_traits
{
template <class...>
struct Args
{
};

template <class... T>
using void_t = void;

template <class T, class args, class = void>
struct has_aSpecificFunctionToA : std::false_type
{
};
template <class T, class... args>
struct has_aSpecificFunctionToA<
    T,
    Args<args...>,
    void_t<decltype(std::declval<T>().aSpecificFunctionToA(std::declval<args>()...))>> : std::true_type
{
};

} // namespace detail_traits
template <class T, class... Args>
using has_aSpecificFunctionToA = typename detail_traits::has_aSpecificFunctionToA<T, detail_traits::Args<Args...>>;


class A
{
  public:
    void aSpecificFunctionToA() {
    std::cout << "aSpecificFunctionToA" << std::endl;
    }
};

class B
{
};

template <typename T>
typename std::enable_if<has_aSpecificFunctionToA<T>::value>::type someFunction(T obj)
{
        obj.aSpecificFunctionToA();
}

template <typename T>
typename std::enable_if<!has_aSpecificFunctionToA<T>::value>::type someFunction(T )
{
        std::cout << "some code for class without aSpecificFunctionToA" << std::endl;
}

int main()
{
    std::cout << has_aSpecificFunctionToA<A>::value << std::endl;
    std::cout << has_aSpecificFunctionToA<B>::value << std::endl;

    someFunction(A{});
    someFunction(B{});
}

Upvotes: 0

Pranjal Kaler
Pranjal Kaler

Reputation: 493

This code prevented the compiler to build that particular if block based on a const bool expression.

const bool flag = std::is_same<T, A>::value;
#if(flag)
{
    obj.aSpecificFunctionToA();
}
#endif

Upvotes: -1

cigien
cigien

Reputation: 60218

If you can use c++17, then you can use if constexpr to conditionally compile code if it satisfies some constraints.

template<typename T>
void someFunction(T obj) {
    if constexpr (std::is_same<T, A>::value)
    {
        obj.aSpecificFunctionToA();
    }
    // ... code for all Ts
}

Before c++17, you can use an overload for A, and put the code that is common to all Ts into a separate function:

template<typename T>
void common_code(T obj) {
  // ... code for all Ts
}

template<typename T>
void someFunction(T obj) {
  common_code(obj);
}

void someFunction(A obj) {
  obj.aSpecificFunctionToA();
  common_code(obj);
}

Upvotes: 3

Related Questions