1

I have this implementation of computing the elementwise product of two index sequences

template<size_t...Is,size_t...Js>
constexpr auto product_sequence_impl( index_sequence<Is...>,
                                      index_sequence<Js...> ) ->
  decltype( index_sequence<(Is*Js)...>() );

template<typename S1, typename S2> using product_sequence = 
decltype( product_sequence_impl( declval<S1>(), declval<S2>() ) );

This works as intended so that when I run the following code

using A = index_sequence<0,1,2>;
using B = index_sequence<3,4,5>;
using C = product_sequence<A,B>;

print_sequence( A{}, cout );
print_sequence( B{}, cout );
print_sequence( C{}, cout );

I see get the desired output

[ 0 1 2 ]
[ 3 4 5 ]
[ 0 4 10 ]

Next I attempted to create a metafunction that which can apply a pairwise result class two sequences:

template<template<size_t,size_t> class binary_mfun>
struct binseq_mfun_impl {

  template<size_t...Is, size_t...Js>
  constexpr auto method( index_sequence<Is...>,
                         index_sequence<Js...> ) ->
    decltype( index_sequence<binary_mfun<Is,Js>::value...>() );

  template<typename S1, typename S2>
  using type = decltype( declval<S1>(), declval<S2>() );
};

template<template<size_t,size_t> class binary_mfun, typename S1, typename S2>
using binseq_mfun = typename binseq_mfun_impl<binary_mfun>::template type<S1,S2>;

Where the pairwise product implementation is

template<size_t I, size_t J> 
struct binary_product { 
  static constexpr size_t value = I*J; 
};

However, when I run this bit of code

using D = binseq_mfun<binary_product,A,B>;
print_sequence( D{}, cout );

I get that D is has the same values as B. It appears that binary_mfun is never being using. I've also tried to implement this using the function approach, but then I am unclear on how to handle the template template parameter

template<template<size_t,size_t> typename binary_mfun, size_t...Is, size_t...Js>
constexpr auto binseq_mfun_impl( binary_mfun /*<?,?>*/,
                                 index_sequence<Is...>,
                                 index_sequence<Js...> ) ->
  index_sequence<binary_mfun<Is,Js>::value...>;

template<typename binary_mfun, typename S1, typename S2>
using binseq_mfun = 
decltype(binseq_mfun_impl( declval<binary_mfun>(), 
                           declval<S1>(), 
                           declval<S2>() ) );
Nikita Kniazev
  • 3,728
  • 2
  • 16
  • 30
Greg von Winckel
  • 2,261
  • 2
  • 16
  • 14
  • 2
    `using type = decltype( declval(), declval() );` should be `using type = decltype( method( declval(), declval() ) );`. – Quentin Sep 25 '18 at 18:11
  • 2
    `decltype( index_sequence<(Is*Js)...>() )` is just `index_sequence<(Is*Js)...>`, no need for the extra typing – Barry Sep 25 '18 at 18:28

1 Answers1

1

Thanks to Quentin and Barry's comments as well as realizing that method needs to be static here is a complete working version:

// Metafunction for binary operations on sequences
template<template<size_t,size_t> class binary_mfun>
struct binseq_mfun_impl {

  template<size_t...Is, size_t...Js>
  static constexpr auto method( index_sequence<Is...>,
                                index_sequence<Js...> ) ->
      index_sequence<binary_mfun<Is,Js>::value...>;

  template<typename S1, typename S2>
  using type = decltype( method( declval<S1>(), declval<S2>() ) );
};

template<template<size_t,size_t> class binary_mfun, typename S1, typename S2>
using binseq_mfun = typename binseq_mfun_impl<binary_mfun>::template type<S1,S2>;   

// Example binary function
template<size_t I, size_t J> 
struct binary_product { static constexpr size_t value = I*J; };

// Example usage
using A = index_sequence<0,1,2>;
using B = index_sequence<3,4,5>;
using C = binseq_mfun<binary_product,A,B>;   // Has values 0,4,10
Greg von Winckel
  • 2,261
  • 2
  • 16
  • 14