Home > database >  Get template parameter of derived class from base object
Get template parameter of derived class from base object

Time:04-14

In short:

  • I have a base class A_base without template parameters and a derived class A that has two.
  • The function foo() only accepts base class objects
  • foo() is supposed to return an object which has the same type as the derived classes' first template parameter T.

The reason for this is that I don't want to specialize foo() for ALL variations of A which you can imagine could be hundreds.

To illustrate this in code:

#include <cstdlib>

struct A_base
{

};

template <typename T, size_t S>
struct A : A_base
{
    using P = T; // <-- how do I get here from base class A?
    T arr[S];
};


template <typename T>
auto foo(const A_base& ref) -> decltype(/* somehow get P*/)
{
    return /* object of type P */;
}

int main()
{
    A<int, 10> a;

    foo(a);
}

I typedefd another parameter P to T because I thought this would make the class "own" the type and provide for better access. I was hoping for a solution without virtual methods, because I got around using virtual calls until now.

CodePudding user response:

The compiler needs to know the return type of foo() at compile time. If you cannot make A_base a template, why not make foo() itself a function template?

As in:

#include <type_traits>

struct A_base{};

template <typename T>
struct B : A_base
{
    static constexpr T val{};
};

template<typename T>
auto foo(const T&)
{
    static_assert(std::is_base_of_v<A_base, T>);  // this works without  
                                                        // depending on a particular
                                                        // constructor
    return T::val;  // for example.
}


struct C {};

int main()
{
    auto x = foo(B<int>{});
    return std::is_same_v<int, decltype(x)>;
}

CodePudding user response:

Sorry for answering my own question but I found a possibility. I just create an intermediary dummy class A_middle with only one template parameter T that is inherited from A. I can then use this intermediary class and not the base class for foo()'s parameters:

#include <cstdlib>

struct A_base {};

template <typename T>
struct A_middle : A_base { };

template <typename T, size_t S>
struct A : A_middle<T>
{
    T arr[S];
};


template <typename T>
T foo(const A_middle<T>& ref) // deduction works as expected
{
    T var;
    return var;
}

int main()
{
    A<int, 10> b;

    foo(b);
}
  • Related