0

鉴于继承在模板类型略有变化后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 
} 
+0

@ max66 [在C++ 17中编译得很好](https://godbolt.org/g/5tKv7Z) – Justin

+0

@Justin - thanks; right:C++ 17 – max66

回答

1

如果接受通过Q<>,而不是Qstd::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>>::typestd::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); 
} 
+0

以及如何分解案例,以便'accumulate > :: type'是'std :: integer_sequence ',其中'T'是任何整型? 'template class Z,T首先, T ...其余,typename C> struct cumulative ,C>从什么继承(不重复实现)? – prestokeys

+0

好的,我找到了你想要的解决方案(不需要重复执行)。我将其添加为答案。 – prestokeys

+0

@prestokeys - 回答修改,但我的改进解决方案基本上相当于您的 – max66

1

在适应max66溶液,我允许的,例如,accumulated<std::integer_sequence<T, 1,2,3,4,5>>::typestd::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。