0

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.

glades
  • 3,778
  • 1
  • 12
  • 34
  • You already have `T` in `foo`, why not take `const T& ref` directly? – Lingxi Apr 13 '22 at 06:06
  • @Lingxi The user shouldn't be bothered to specify the template parameter. It should auto deduce it. – glades Apr 13 '22 at 09:46
  • C++ doesn't work this way. You never know the derived type by given only the reference/pointer to base object, unless the base class have type info about the derived class, e.g. it is polymorphic and try `dynamic_cast` it to each of ALL possible derived class, or it has custom data member that indicates the derived class type, then you can write branch code for each of ALL possible derived class. – VainMan Apr 13 '22 at 10:03

2 Answers2

0

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)>;
}
Michaël Roy
  • 6,338
  • 1
  • 15
  • 19
0

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);
}
glades
  • 3,778
  • 1
  • 12
  • 34