简体   繁体   中英

How to do static dispatch base on derivation on a template

How can I specialized a template function to return true if objects belong to certain templates/classes and false for other templates/classes no classes have virtual functions. I have a template:

template<typename t1, typename t2, bool a> struct DynamicData{...}

which I want to do special processing, or any class derived from that template. in the following example I have a specialization of DynamicData<> : DynamicDataSym<> for which I did a specialization of is_dynamic<> , but because DynamicDataSym<> is derived from DynamicData<> I wonder if there is a way that anytime I create a new derive class from DynamicData<> I can have is_dynamic<> work automatically.

the design with the templates cannot be changed, and no virtual methods are allowed, Also working with C++17, so c++20 & C++23 out of the equation!

class ClrngAssetBuff
{
   int name1 {};

public:
   int GetName();
};


template<typename t1, typename t2, bool a>
struct DynamicData
{
   t1 m1;
   t2 m2;
};

template<typename t1, typename t2, int sym>
struct DynamicDataSym : DynamicData<t1, t2, true>
{
   int some() { return sym; }
};

template<typename t1>
struct DynamicDataSym2 : DynamicData<t1, float, true>
{
   float some() { return 1.0f; }
};


template<typename T>
constexpr bool is_dynamic(const T& t)
{
   return false;
}

template<typename T1, typename T2, bool a>
constexpr bool is_dynamic(const DynamicData<T1, T2, a>& t)
{
   return true;
}

template<typename T1, typename T2, int a>
constexpr bool is_dynamic(const DynamicDataSym<T1, T2, a>& t)
{
   return true;
}

template<typename T>
constexpr bool is_dynamic2()
{
    return is_dynamic<>(T {});
}


template<typename T> void DoDynamicInfo(const T& t);
template<typename T> void ExecuteMessage(const T& t);

template<typename T>
void ProcessMessage(const T& t)
{
   if  (is_dynamic2<T>())
      DoDynamicInfo(t);

    ExecuteMessage(t);
}

int main(int argc, char** argv)
{
    ClrngAssetBuff msg1;
    ProcessMessage(msg1);

    DynamicData<int, double, false> msg2;
    ProcessMessage(msg2);
    DynamicDataSym<int, int, 10> msg3;
    ProcessMessage(msg3);

    DynamicDataSym2<long long> msg4;
    ProcessMessage(msg4);               // oops should call DoDynamicInfo(msg4)
}

If I correctly understand what do you want... you're looking for something as follows

template <typename T1, typename T2, bool B>
std::true_type is_dynamic_helper (DynamicData<T1, T2, B> *);

std::false_type is_dynamic_helper (...);

template <typename T>
constexpr auto is_dynamic
   = decltype(is_dynamic_helper(std::declval<T*>()))::value;

that is a template variable (available starting from C++14, so is good for a C++17 solution) that is true when a pointer of the template T type can be converted to a DynamicData<T1, T2, B> (for generics T1 , T2 types and a generic boolean B value), false otherwise.

So is_dynamic is true when T is a DynamicData or derive from a DynamicData . Unfortunately this doesn't works when T derive from two or more DynamicData classes.

Observe that I've made is_dynamic a constexpr variable, so you can use is constexpr , if you want, inside ProcessMessage()

template <typename T>
void ProcessMessage(const T& t)
{
  if constexpr ( is_dynamic<T> )
    DoDynamicInfo(t);

  ExecuteMessage(t);
}

The following is a full compiling C++17 example

#include <iostream>

class ClrngAssetBuff
{
  int name1 {};

  public:
     int GetName();
};

template <typename t1, typename t2, bool a>
struct DynamicData
{ t1 m1; t2 m2; };

template <typename t1, typename t2, int sym>
struct DynamicDataSym : DynamicData<t1, t2, true>
{ int some() { return sym; } };

template <typename t1>
struct DynamicDataSym2 : DynamicData<t1, float, true>
{ float some() { return 1.0f; } };

template <typename T>
void DoDynamicInfo(const T& t)
{ std::cout << "Do Dynamic Info" << std::endl; }

template <typename T>
void ExecuteMessage(const T& t)
{ std::cout << "Execute Message" << std::endl; }

template <typename T1, typename T2, bool B>
std::true_type is_dynamic_helper (DynamicData<T1, T2, B> *);

std::false_type is_dynamic_helper (...);

template <typename T>
constexpr auto is_dynamic
   = decltype(is_dynamic_helper(std::declval<T*>()))::value;

template <typename T>
void ProcessMessage(const T& t)
{
  if constexpr ( is_dynamic<T> )
    DoDynamicInfo(t);

  ExecuteMessage(t);
}

int main()
{
  ClrngAssetBuff msg1;

  std::cout << "---- msg1" << std::endl;

  ProcessMessage(msg1);

  DynamicData<int, double, false> msg2;

  std::cout << "---- msg2" << std::endl;

  ProcessMessage(msg2);
  DynamicDataSym<int, int, 10> msg3;

  std::cout << "---- msg3" << std::endl;

  ProcessMessage(msg3);

  DynamicDataSym2<long long> msg4;

  std::cout << "---- msg4" << std::endl;

  ProcessMessage(msg4);  // now call DoDynamicInfo(msg4)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM