C++ 从多重继承确定模板包
考虑以下代码:C++ 从多重继承确定模板包,c++,templates,c++11,inheritance,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, B
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>();
}
enum品牌{a,b,c,d,e,f,g,h,i,j};
模板结构A{};
结构B:A,A,A{};
结构C:A,A,A,A,A{};
模板void foo(){}
int main(){
foo();
foo();
}
foo()由于B的多重继承,代码>仅在我的(真实)程序中有意义,如果它有a,d,i
作为参数。然而,a,d,i
应该是可以推断的,否则如果我改变B的继承,就会有维护问题。这同样适用于foo()代码>
我一直在写template struct GetBrands
以从T
获取Brand
元素的可推断包。任何帮助都将不胜感激。现在,让我们假设A中的最高int值是10。好的,这里是我的第二个解决方案,用来替换第一个。通过引入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
}
#包括
#包括
枚举品牌{a,b,c,d,e,f,g,h,i,j,FirstBrand=a,LastBrand=j};
模板结构HigherBase{};
模板结构A:HigherBase{};
结构B:A,A,A{};
结构C:A,A,A,A,A{};
模板结构GetBrandsHelper;
模板
结构GetBrandsHelper:
std::conditional::type{};
模板结构标识{using type=type;};
模板
结构GetBrandsHelper:
std::conditional::type{};
模板结构FooPack{};
模板
结构GetBrands:GetBrandsHelper{};
//模板
//void foo(){}
//专门化foo以测试输出。
模板
void foo(){std::cout如果我们将问题迎头痛击,(稍微)改变了编写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
}
#包括
枚举品牌{a,b,c,d,e,f,g,h,i,j};
模板结构A{};
模板结构A_基础;
模板结构A_基:A..{};
结构B:A_基{};
结构C:A_基{};
//模板void foo(){}
//*重载*foo以测试输出。
模板
void foo(){std::cout是“品牌”s保证唯一?@T.C.很好。如果不是唯一的,我的算法确实会崩溃。所以我没有一个完整的通用解决方案。如果a有两个以上的模板参数,我的解决方案也会崩溃。这说明我的解决方案相当糟糕。我用我的新解决方案解决了上面提到的第二个问题,在这里我介绍了C重复的问题仍然存在。