从多重继承确定模板包

时间:2015-05-11 22:50:59

标签: c++ templates c++11 inheritance

考虑以下代码:

enum Brand {a,b,c,d,e,f,g,h,i,j};

template <Brand, int> struct A {};

struct B : A<a,4>, A<d,0>, A<i,3> {};
struct C : A<b,0>, A<c,5>, A<e,1>, A<h,4>, A<j,0> {};

template <typename, Brand...> void foo() {}

int main() {
    foo<B, a,d,i>();
    foo<C, b,c,e,h,j>();
}

foo<B, a,d,i>();仅在我的(真实)程序中才有意义,因为它有a,d,i作为参数,因为B的多重继承。但是,a,d,i应该以某种方式推断,否则如果我改变了B的继承,就会出现维护问题。 foo<C, b,c,e,h,j>();

也是如此

我很难写出template <typename T> struct GetBrands来从Brand获取T元素的可推导包。任何帮助,将不胜感激。现在,让我们假设A中最高的int值是10.

2 个答案:

答案 0 :(得分:1)

如果我们解决了问题,并(略微)改变了您编写BC类定义的方式,该怎么办?

下面,我从你的回答中借用了测试代码:

#include <iostream>

enum Brand {a,b,c,d,e,f,g,h,i,j};

template<Brand, int> struct A { };


template<typename...> struct A_base;
template<Brand... Brands, int... Is> struct A_base<A<Brands, Is>...> : A<Brands, Is>... { };


struct B : A_base<A<a,4>, A<d,0>, A<i,3>> { };
struct C : A_base<A<b,0>, A<c,5>, A<e,1>, A<h,4>, A<j,0>> { };

//template<typename, Brand...> void foo() { }

// *Overloading* foo in order to test the outputs.
template<typename, Brand x, Brand y, Brand z>
void foo() { std::cout << x << ' ' << y << ' ' << z << '\n'; }

template<typename, Brand x, Brand y, Brand z, Brand u, Brand v>
void foo() { std::cout << x << ' ' << y << ' ' << z << ' ' << u << ' ' << v << '\n'; }


template<typename S, Brand... Brands, int... Is> void foo_helper(A_base<A<Brands, Is>...>) 
{ 
    foo<S, Brands...>();
}

template<typename S> void bar() { foo_helper<S>(S()); }


int main()
{
    bar<B>();  // Supposed to be the same as foo<B, a,d,i>();  // 0 3 8
    bar<C>();  // Supposed be the same as foo<C, b,c,e,h,j>();  // 1 2 4 7 9
}

我认为这可以用来处理你需要的更一般的案例。

答案 1 :(得分:0)

好的,这是我的第二个替换第一个的解决方案。通过引入A的基类,我现在允许算法工作,无论A有多少模板参数(只要我们只关注A的第一个组件)。解决方案现在也缩短了。

#include <iostream>
#include <type_traits>

enum Brand {a,b,c,d,e,f,g,h,i,j, FirstBrand = a, LastBrand = j};

template <Brand> struct HigherBase {};
template <Brand X, int> struct A : HigherBase<X> {};

struct B : A<a,4>, A<d,0>, A<i,3> {};
struct C : A<b,0>, A<c,5>, A<e,1>, A<h,4>, A<j,0> {};

template <typename T, Brand Current, typename Output> struct GetBrandsHelper;

template <typename T, Brand Current, template <Brand...> class P, Brand... Output>
struct GetBrandsHelper<T, Current, P<Output...>> :
    std::conditional<std::is_base_of<HigherBase<Current>, T>::value,
        GetBrandsHelper<T, static_cast<Brand>(Current + 1), P<Output..., Current>>,
        GetBrandsHelper<T, static_cast<Brand>(Current + 1), P<Output...>>
    >::type {};

template <typename Type> struct Identity { using type = Type; };

template <typename T, template <Brand...> class P, Brand... Output>
struct GetBrandsHelper<T, LastBrand, P<Output...>> :
    std::conditional<std::is_base_of<HigherBase<LastBrand>, T>::value,
        Identity<P<Output..., LastBrand>>,
        Identity<P<Output...>>
    >::type {};

template <Brand...> struct FooPack {};

template <typename T>
struct GetBrands : GetBrandsHelper<T, FirstBrand, FooPack<>> {};

//template <typename, Brand...>
//void foo() {}

// Specializing foo in order to test the outputs.
template <typename, Brand x, Brand y, Brand z>
void foo() {std::cout << x << ' ' << y << ' ' << z << '\n';}

template <typename, Brand x, Brand y, Brand z, Brand u, Brand v>
void foo() {std::cout << x << ' ' << y << ' ' << z << ' ' << u << ' ' << v << '\n';}

template <typename T, Brand... Is>
void fooHelper (const FooPack<Is...>&) {
    foo<T, Is...>();
}

template <typename T>
void bar() {
    fooHelper<T> (typename GetBrands<T>::type());
}

int main() {
    bar<B>();  // Supposed to be the same as foo<B, a,d,i>();  // 0 3 8
    bar<C>();  // Supposed be the same as foo<C, b,c,e,h,j>();  // 1 2 4 7 9
}

仍然需要一些概括:

1)如果允许重复Brand个元素怎么办?

2)如果A有N个模板参数,我们想要对N个组件中的任何一个执行上述操作,该怎么办?根据N和指定的组件位置P来处理它的一般算法是什么(上述解是N = 2的特殊情况,P = 0)?因此,如果我们想要为所有 N个A组件执行此操作,我们将使用相同的算法,但每次只更改P的值。