继承在模板类型略有变化后traits类
template <int...> struct Z; template <int...> struct Q;
template <std::size_t...> struct I;
假设我们要
accumulated_sums<Z<1,2,3,4,5>, Q>::type
是
Q<1,3,6,10,15>
和
accumulated<I<1,2,3,4,5>, std::integer_sequence>::type
是
std::index_sequence<1,3,6,10,15>
有没有办法从accumulated_sums
类的一些继承方案定义accumulated
类?它们的操作方式完全相同,唯一不同的是模板类型template <T...> class
对于accumulated_sums
而对于accumulated
稍有不同template <typename U, U...> class
。否则,即使它们的定义基本相同,我也必须分别定义这两个类。应该有一些方法来为两个类定义一次。这里是我为这两个类完全编译的代码,并且您可以看到它们在代码中基本相同。
#include <iostream>
#include <type_traits>
#include <utility>
namespace detail {
template <typename Pack> struct sequence_traits;
template <typename T, template <T...> class Z, T... Is>
struct sequence_traits<Z<Is...>> {
using type = T;
template <T... Js>
using templ_type = Z<Js...>;
};
}
// accumulated_sums
template <typename T, typename Output, template <T...> class, T...> struct accumulated_sums_h;
template <typename T, template <T...> class Z, template <T...> class Q, T Sum, T... Is>
struct accumulated_sums_h<T, Z<Sum, Is...>, Q> {
using type = Q<Is..., Sum>;
};
template <typename T, template <T...> class Z, T Sum, T... Is, template <T...> class Q, T Next, T... Rest>
struct accumulated_sums_h<T, Z<Sum, Is...>, Q, Next, Rest...> :
accumulated_sums_h<T, Z<Sum + Next, Is..., Sum>, Q, Rest...> {};
template <typename Sequence,
template <typename detail::sequence_traits<Sequence>::type...> class = detail::sequence_traits<Sequence>::template templ_type>
struct accumulated_sums;
template <typename T, template <T...> class Z, T First, T... Rest, template <T...> class Q>
struct accumulated_sums<Z<First, Rest...>, Q> :
accumulated_sums_h<T, Z<First>, Q, Rest...> {};
// accumulated
template <typename T, typename Output, template <typename U, U...> class, T...> struct accumulated_h;
template <typename T, template <T...> class Z, template <typename U, U...> class Q, T Sum, T... Is>
struct accumulated_h<T, Z<Sum, Is...>, Q> {
using type = Q<T, Is..., Sum>;
};
template <typename T, template <T...> class Z, T Sum, T... Is, template <typename U, U...> class Q, T Next, T... Rest>
struct accumulated_h<T, Z<Sum, Is...>, Q, Next, Rest...> :
accumulated_h<T, Z<Sum + Next, Is..., Sum>, Q, Rest...> {};
template <typename Sequence, template <typename U, U...> class Q> struct accumulated;
template <typename T, template <T...> class Z, T First, T... Rest, template <typename U, U...> class Q>
struct accumulated<Z<First, Rest...>, Q> :
accumulated_h<T, Z<First>, Q, Rest...> {};
// Testing
template <int...> struct Z;
template <int...> struct Q;
template <std::size_t...> struct I;
int main() {
std::cout << std::boolalpha << std::is_same<
accumulated_sums<Z<1,2,3,4,5>, Q>::type,
Q<1,3,6,10,15>
>::value << '\n'; // true
std::cout << std::is_same<
accumulated_sums<Z<1,2,3,4,5>>::type,
Z<1,3,6,10,15>
>::value << '\n'; // true
std::cout << std::is_same<
accumulated<Z<1,2,3,4,5>, std::integer_sequence>::type,
std::integer_sequence<int, 1,3,6,10,15>
>::value << '\n'; // true
std::cout << std::is_same<
accumulated<I<1,2,3,4,5>, std::integer_sequence>::type,
std::index_sequence<1,3,6,10,15>
>::value << '\n'; // true
}
如果接受通过Q<>
,而不是Q
和std::integer_sequence<int>
(或std::integer_sequence<std::size_t>
)代替std::integer_sequence
(这样的模板类型,而不是一个模板,模板类型),你可以用叉子叉的情况下(有或没有第一类型模板)在底部(见下面例子中的accumulated_h2
),而不是顶部
所以你可以使用accumulated
这两种情况,并剔除accumulated_sum
。
以下是一个完整的工作示例。
#include <type_traits>
#include <utility>
namespace detail
{
template <typename Pack>
struct sequence_traits;
template <typename T, template <T...> class Z, T... Is>
struct sequence_traits<Z<Is...>>
{ using templ_empty = Z<>; };
}
// accumulated
template <typename T, typename, T...>
struct accumulated_h2;
template <typename T, template <typename, T ...> class Q, T ... Ts>
struct accumulated_h2<T, Q<T>, Ts...>
{ using type = Q<T, Ts...>; };
template <typename T, template <T ...> class Q, T ... Ts>
struct accumulated_h2<T, Q<>, Ts...>
{ using type = Q<Ts...>; };
template <typename T, typename, typename, T...>
struct accumulated_h;
template <typename T, template <T...> class Z, typename C, T Sum, T... Is>
struct accumulated_h<T, Z<Sum, Is...>, C>
{ using type = typename accumulated_h2<T, C, Is..., Sum>::type; };
template <typename T, template <T...> class Z, T Sum, T... Is,
typename C, T Next, T... Rest>
struct accumulated_h<T, Z<Sum, Is...>, C, Next, Rest...>
: accumulated_h<T, Z<Sum + Next, Is..., Sum>, C, Rest...>
{ };
template <typename T,
typename = typename detail::sequence_traits<T>::templ_empty>
struct accumulated;
template <typename T, template <T...> class Z, T First,
T... Rest, typename C>
struct accumulated<Z<First, Rest...>, C>
: accumulated_h<T, Z<First>, C, Rest...>
{ };
// Testing
template <int...>
struct Z;
template <int...>
struct Q;
template <std::size_t...>
struct I;
int main()
{
static_assert(std::is_same<
accumulated<Z<1,2,3,4,5>, Q<>>::type,
Q<1,3,6,10,15>>::value, "!");
static_assert(std::is_same<
accumulated<Z<1,2,3,4,5>>::type,
Z<1,3,6,10,15>>::value, "!");
static_assert(std::is_same<
accumulated<Z<1,2,3,4,5>, std::integer_sequence<int>>::type,
std::integer_sequence<int, 1,3,6,10,15>>::value, "!");
static_assert(std::is_same<
accumulated<I<1,2,3,4,5>, std::integer_sequence<std::size_t>>::type,
std::index_sequence<1,3,6,10,15>>::value, "!");
}
- 编辑 -
的OP问
而如何叉的情况下,使
accumulated<std::integer_sequence<T, 1,2,3,4,5>>::type
是std::integer_sequence<T, 1,3,6,10,15>
,其中T
是任何整型?
我看过你的解决方案,我已经准备了一个又一个,不是一个很大的不同:扔了旧Z
,我已经与std::integer_sequence
而不是你的squeeze
取代它。
以下是我的代码。
#include <type_traits>
#include <utility>
namespace detail
{
template <typename Pack>
struct sequence_traits;
template <typename T, template <typename, T...> class Z, T... Is>
struct sequence_traits<Z<T, Is...>>
{ using templ_empty = Z<T>; };
template <typename T, template <T...> class Z, T... Is>
struct sequence_traits<Z<Is...>>
{ using templ_empty = Z<>; };
}
// accumulated
template <typename T, typename, T...>
struct accumulated_h2;
template <typename T, template <typename, T ...> class Q, T ... Ts>
struct accumulated_h2<T, Q<T>, Ts...>
{ using type = Q<T, Ts...>; };
template <typename T, template <T ...> class Q, T ... Ts>
struct accumulated_h2<T, Q<>, Ts...>
{ using type = Q<Ts...>; };
template <typename T, typename, typename, T...>
struct accumulated_h;
template <typename T, typename C, T Sum, T... Is>
struct accumulated_h<T, std::integer_sequence<T, Sum, Is...>, C>
{ using type = typename accumulated_h2<T, C, Is..., Sum>::type; };
template <typename T, T Sum, T... Is, typename C, T Next, T... Rest>
struct accumulated_h<T, std::integer_sequence<T, Sum, Is...>, C, Next,
Rest...>
: accumulated_h<T, std::integer_sequence<T, Sum + Next, Is..., Sum>,
C, Rest...>
{ };
template <typename T,
typename = typename detail::sequence_traits<T>::templ_empty>
struct accumulated;
template <typename T, template <T...> class Z, T First,
T... Rest, typename C>
struct accumulated<Z<First, Rest...>, C>
: accumulated_h<T, std::integer_sequence<T, First>, C, Rest...>
{ };
template <typename T, template <typename, T...> class Z, T First,
T... Rest, typename C>
struct accumulated<Z<T, First, Rest...>, C>
: accumulated_h<T, std::integer_sequence<T, First>, C, Rest...>
{ };
// Testing
template <int...>
struct Z;
template <int...>
struct Q;
template <std::size_t...>
struct I;
int main()
{
static_assert(std::is_same<
accumulated<Z<1,2,3,4,5>, Q<>>::type,
Q<1,3,6,10,15>>::value, "!");
static_assert(std::is_same<
accumulated<Z<1,2,3,4,5>>::type,
Z<1,3,6,10,15>>::value, "!");
static_assert(std::is_same<
accumulated<Z<1,2,3,4,5>, std::integer_sequence<int>>::type,
std::integer_sequence<int, 1,3,6,10,15>>::value, "!");
static_assert(std::is_same<
accumulated<I<1,2,3,4,5>, std::integer_sequence<std::size_t>>::type,
std::index_sequence<1,3,6,10,15>>::value, "!");
static_assert(std::is_same<
accumulated<std::index_sequence<1,2,3,4,5>>::type,
std::index_sequence<1,3,6,10,15>>::value);
static_assert(std::is_same<
accumulated<std::index_sequence<1,2,3,4,5>, I<>>::type,
I<1,3,6,10,15>>::value);
}
以及如何分解案例,以便'accumulate
好的,我找到了你想要的解决方案(不需要重复执行)。我将其添加为答案。 – prestokeys
@prestokeys - 回答修改,但我的改进解决方案基本上相当于您的 – max66
在适应max66溶液,我允许的,例如,accumulated<std::integer_sequence<T, 1,2,3,4,5>>::type
是std::integer_sequence<T, 1,3,6,10,15>
,其中T是任何整数类型。重复实施已被避免。以下编译GCC 7。2:
#include <type_traits>
#include <utility>
namespace detail {
template <typename Pack>
struct sequence_traits;
template <typename T, template <T...> class Z, T... Is>
struct sequence_traits<Z<Is...>>
{ using templ_empty = Z<>; };
template <typename T, template <typename U, U...> class Z, T... Is>
struct sequence_traits<Z<T, Is...>>
{ using templ_empty = Z<T>; };
}
// accumulated
template <typename T, typename EmptyContainer, T...>
struct accumulated_h2;
template <typename T, template <typename U, U...> class Q, T ... Ts>
struct accumulated_h2<T, Q<T>, Ts...>
{ using type = Q<T, Ts...>; };
template <typename T, template <T...> class Q, T ... Ts>
struct accumulated_h2<T, Q<>, Ts...>
{ using type = Q<Ts...>; };
template <typename T, typename Sequence, typename, T...>
struct accumulated_h;
template <typename T, template <T...> class Z, typename EmptyContainer, T Sum, T... Is>
struct accumulated_h<T, Z<Sum, Is...>, EmptyContainer>
{ using type = typename accumulated_h2<T, EmptyContainer, Is..., Sum>::type; };
template <typename T, template <T...> class Z, T Sum, T... Is,
typename EmptyContainer, T Next, T... Rest>
struct accumulated_h<T, Z<Sum, Is...>, EmptyContainer, Next, Rest...>
: accumulated_h<T, Z<Sum + Next, Is..., Sum>, EmptyContainer, Rest...>
{ };
template <typename Sequence,
typename = typename detail::sequence_traits<Sequence>::templ_empty>
struct accumulated;
template <typename T, template <T...> class Z, T First,
T... Rest, typename EmptyContainer>
struct accumulated<Z<First, Rest...>, EmptyContainer>
: accumulated_h<T, Z<First>, EmptyContainer, Rest...>
{ };
////// Added //////
template <typename T> struct squeeze {
template <T... Is> struct Z;
template <T... Is>
using templ_type = Z<Is...>;
};
template <typename T, template <typename U, U...> class Z, T First,
T... Rest, typename EmptyContainer>
struct accumulated<Z<T, First, Rest...>, EmptyContainer>
: accumulated_h<T, typename squeeze<T>::template templ_type<First>, EmptyContainer, Rest...>
{ };
/////////
// Testing
template <int...>
struct Z;
template <int...>
struct Q;
template <std::size_t...>
struct I;
int main()
{
static_assert(std::is_same<
accumulated<Z<1,2,3,4,5>, Q<>>::type,
Q<1,3,6,10,15>>::value);
static_assert(std::is_same<
accumulated<Z<1,2,3,4,5>>::type,
Z<1,3,6,10,15>>::value);
static_assert(std::is_same<
accumulated<Z<1,2,3,4,5>, std::integer_sequence<int>>::type,
std::integer_sequence<int, 1,3,6,10,15>>::value);
static_assert(std::is_same<
accumulated<I<1,2,3,4,5>, std::integer_sequence<std::size_t>>::type,
std::index_sequence<1,3,6,10,15>>::value);
// Added
static_assert(std::is_same<
accumulated<std::index_sequence<1,2,3,4,5>>::type,
std::index_sequence<1,3,6,10,15>>::value);
}
更新:感谢max66的想法,我全身甚至进一步任意数量的序列:https://ideone.com/FBWApu 代码编译使用GCC 7.2,但ideone失败,因为它仅使用C++ 14。
@ max66 [在C++ 17中编译得很好](https://godbolt.org/g/5tKv7Z) – Justin
@Justin - thanks; right:C++ 17 – max66