在继承树中初始化元组

时间:2017-07-31 07:03:09

标签: c++ inheritance tuples

让B类成为A的基础:

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

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

有没有办法将派生属性元组添加到基本属性元组?例如通过某种形式的CRTP?我知道基类和派生类型的属性在编译时是已知的,但我似乎无法弄清楚如何组合不同继承级别的属性。

3 个答案:

答案 0 :(得分:3)

您可以使用variadic templates向基类的properties成员添加更多类型(B)。如果您希望在派生类中也有基类的构造函数,可以使用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");
}

可以通过函数模板实现将class B的派生类传递给同一函数:

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

Live Demo

答案 1 :(得分:2)

如果相关,您可以使用以下内容:

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 :(得分:1)

当你想到CRTP时,你几乎拥有它。

您可以执行以下操作:

// 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>;
};

您可以在Coliru

上看到有效的演示