简体   繁体   中英

How to construct a template that can call and return two different types

I'm working on some code where I have two classes each with a method that returns said class with a specific value. Now these two class have different names and the methods which returns said class with a specific value have different names, however the value is the same.

example

   class_a a = class_a::get_value_a()
   class_b b = class_b::get_value_b()

   a.value() == b.value() is true

Now what I'm trying to make is a generic way to get this value using template

example

   class_generic g_a = class_generic::get_value<class_a>();
   class_generic g_b = class_generic::get_value<class_b>();

   g_a.value() == g_b.value() is true

But when making the template I tried to do the following

template <typename T> T class_generic::get_value()
{
  if (typeid(T).hash_code() == typeid(class_a).hash_code())
  {
    return class_a::get_value_a()
  }
  if (typeid(T).hash_code() == typeid(class_b).hash_code())
  {
    return class_b::get_value_b();
  }
}

But this will not compile and it seems to me that it tries to resolve both return types and converts one.

So how do I do this correctly?

regards

You can apply template specialization . eg

// primary template
template <typename T> 
T class_generic::get_value();

// explicit specialization for T = class_a
template <> 
class_a class_generic::get_value<class_a>()
{
  return class_a::get_value_a();
}

// explicit specialization for T = class_b
template <> 
class_b class_generic::get_value<class_b>()
{
  return class_b::get_value_b();
}

Or apply Constexpr If (since C++17), whose condition is evaluated at compile-time, and then could avoid the issue your code snippet encountered. eg

template <typename T>
T class_generic::get_value()
{
  if constexpr (std::is_same_v<T, class_a>)
  {
    return class_a::get_value_a();
  } 
  else if constexpr (std::is_same_v<T, class_b>)
  {
    return class_b::get_value_b();
  } 
  else 
  {
    // return something else..
  }
}

In current Standard, this can be done as

struct class_generic {
    template<typename T> T get_value() {
        if constexpr(std::is_same_v<T, class_a>) {
            return class_a::get_value_a();
        }
        else return class_b::get_value_b();
    }
};

Note that if the two alternatives cannot be compiled simultaneously, ie one part of code only compiles for one template parameter value, and other for the other, they should be different branches of the same if constexpr/else operator.

Aside the proper solutions already given, you should notice that typeid() is a runtime operator to inspect polymorphic type at runtime, whether templates are a compile time issue. Thus typeid would not be evaluated during template evaluation in your code.

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