Initialize a tuple through an inheritance tree

Let class B be the base of A:

class B
{
public:
    std::tuple<int, bool, float> properties.
}

class A : public B
{
public:
    std::tuple<float, std::string, std::string> derivedProperties.
}

      

Is there a way to add a set of derived derived tuples to a tuple of basic propositions? For example, some form of CRTP? I know that the properties of the base class and derived types are known at compile time, but I cannot figure out how to combine properties of different levels of inheritance.

+3


source to share


3 answers


You almost had it when you thought about CRTP.

You can do the following:



// We need this boilerplate to overcome
// the incompleteness of "Derived" when instantiating "Base<Derived>"
template <typename T>
struct properties {
    using type = std::tuple<>;
};

class Derived;

template <>
struct properties<Derived> {
    using type = std::tuple<float, std::string, std::string>;
};

// Now that we defined our properties
template <typename Derived>
class Base {
public:
    using derived_properties_t = typename properties<Derived>::type; // Should be a tuple
    using base_properties_t = std::tuple<int, bool, float>;
    using combined_properties_t = decltype(std::tuple_cat(std::declval<base_properties_t>(),
                                                          std::declval<derived_properties_t>()));
    combined_properties_t properties;
};

class Derived : public Base<Derived> {
public:
    using properties_type = std::tuple<float, std::string, std::string>;
};

      

You can see a working demo at Coliru

+1


source


You can use variadic templates to add more types to properties

your base class element ( B

). If you want to have base class constructors in a derived class, you can use using-declaration :

#include <string>
#include <tuple>

template<typename... Ts>
class B {
public:
    B(int i, bool b, float f, const Ts&... rest) :
            properties(std::make_tuple(i, b, f, rest...)) {
    }
    std::tuple<int, bool, float, Ts...> properties;
};

class A : public B<float, std::string, std::string> {
    using B::B;
};

int main() {
    A foo(12, true, 3.14, 6.28, "foo", "bar");
}

      




Passing derived classes class B

to the same function can be achieved using function templates:

template<typename... Ts>
void test(const B<Ts...>& base);

      

Live Demo

+3


source


You can use the following if needed:

template <typename ... Ts>
class C
{
public:
    std::tuple<int, bool, float, Ts...> properties.
};

using B = C<>;
using A = C<float, std::string, std::string>;

      

+2


source







All Articles