考虑以下代码:
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.
答案 0 :(得分:1)
如果我们解决了问题,并(略微)改变了您编写B
和C
类定义的方式,该怎么办?
下面,我从你的回答中借用了测试代码:
#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的值。