Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to define a template member in a non-template class?

Say I have a class template named Compute, and another class named Function_A with a member function template:

template <typename T> void Evaluate(T parameter)

I am constrained to use the class Function_A as it is. I already know that T can only be one of two types type_1 and type_2.

Is there a way to have something similar to Compute<T> C as a member variable of Function_A instead of defining a local Compute<T> object inside Evaluate(...)? I know that this is against the philosophy of using templates, hence it is likely not possible, but can ideally be done in that case instead?

I tried to have two members Compute<type_1> C1 and Compute<type_2> C2 in Function_A, and then use them under an if (typeid(T) == typeid(type_1)) but it's a pretty hideous, and against the philosophy of using templates as well.

Just to illustrate what I mean:

template <class T>
class Compute
{
public:
  T Function_B(T parameter)
    {
      return f.eval(parameter);
    }

private:
  SomeClass<T> f;
}

And a class:

class Function_A
{
  public:
    template <typename T> T Evaluate(T parameter)
    {
      Compute<T> C; //this is very expensive!
      T value = C.Function_B(parameter);
      return value;
    }

  private:
    double SomeParameter;
    //Compute<T> C; //conceptually what I want
}
like image 660
Rabah Avatar asked Mar 26 '19 12:03

Rabah


People also ask

Can a non template class have a template member function?

A non-template class can have template member functions, if required. Notice the syntax. Unlike a member function for a template class, a template member function is just like a free template function but scoped to its containing class.

How would you define member function outside the class template?

Member functions of class templates (C++ only) You may define a template member function outside of its class template definition. The overloaded addition operator has been defined outside of class X . The statement a + 'z' is equivalent to a. operator+('z') .

Can member functions be declared as template?

Member functions can be function templates in several contexts. All functions of class templates are generic but are not referred to as member templates or member function templates. If these member functions take their own template arguments, they are considered to be member function templates.

Can a member function template be virtual?

Member template functions cannot be virtual functions and cannot override virtual functions from a base class when they are declared with the same name as a base class virtual function.


2 Answers

How about (untested):

class Function_A
{
  public:
    template <typename T> void Evaluate(T parameter)
    {
      T value = std::get<Compute<T>>(computers).Function_B(parameter);
      return T(SomeParameter) * value;
    }

  private:
    double SomeParameter;
    std::tuple<Compute<type_1>, Compute<type_2>> computers;
};

Note: std::pair would work exactly the same as std::tuple here, if you fancy the first/second semantics it adds.

Additionally, note that T(SomeParameter) is a C-style cast, which could be problematic if T is not a class type. Consider T{} or static_cast<T>().

like image 127
Quentin Avatar answered Sep 18 '22 07:09

Quentin


One thing you can do is make C static. If you have

template <typename T> void Evaluate(T parameter)
{
  static Compute<T> C; // only do this once per T now
  T value = C.Function_B(parameter);
  return T(SomeParameter)*value;
}

then when you call Evaluate with type_1 you'll have one version of the function that has C<type_1> in it that will only be constructed the first time the function is called and the same thing happens for type_2.

like image 30
NathanOliver Avatar answered Sep 20 '22 07:09

NathanOliver