2

I would like to have a class that has a constructor which takes a variadic number of arguements and fills an array with it by unpacking somehow to a comma initializer list which is supported by the array, here the example:

class A{
    public:
    template<typename ...T>
    A(T ... values): arr(sizeof...(T)) {
         //convert the values somehow that the parameter pack is expanded in the comma initialized list as the following:

         //arr << values1, values2, values3,... , valuesN
    }

    ArrayType arr;

}

This comma initialization method is especially the case for ArrayType beeing a Eigen::Matrix class ( arr << 1,2,3; ). I was wondering if the following is doable and if there is some other elegant way to fill the array in the case we can use the index operator (i) to the i-th element :-)

Thanks alot :)

Gabriel
  • 8,990
  • 6
  • 57
  • 101

1 Answers1

1
#include <utility>

template<typename T0, typename... Ts>
struct comma_collapse { typedef T0 type; };
template<typename T0, typename T1, typename... Ts>
struct comma_collapse<T0, T1, Ts...> {
    typedef decltype( std::declval<T0>(), std::declval<typename comma_collapse<T1, Ts...>::type>() ) type;
};

template<typename LHS>
LHS&& comma_splice(LHS&& lhs){ return std::forward<LHS>(lhs); }

template<typename LHS, typename RHS, typename... Tail>
typename comma_collapse<LHS,RHS,Tail...>::type&& comma_splice( LHS&& lhs, RHS&& rhs, Tail&&... tail )
{
  auto&& first_two = (std::forward<LHS>(lhs),std::forward<RHS>(rhs));
  return comma_splice(
    std::forward<decltype(first_two)>(first_two),
    std::forward<Tail>(tail)...
  );
}

Then implement the constructor like this:

template<typename T0, typename... Ts>
A(T0&& t0, Ts&& ... ts): arr(sizeof...(Ts)) {
  comma_splice( (arr << std::forward<T0>(t0)), std::forward<Ts>(ts)... );
}

if you want a zero-argument version, create a separate overload (as doing it in one pass isn't practical).

live example

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • The `comma_collapse` exists merely to deal with the problem that both GCC and CLANG refuse to check `comma_splice` itself when I use it recursively in the return type determination of `comman_splice`, and only want to use the earlier overload. I don't know if they are right. So I manually resolve what the type will be in `comma_collapse`. – Yakk - Adam Nevraumont Mar 06 '14 at 22:45
  • Recursively referring to the return type in a function template requires ADL, as the return type is part of the declarator, and therefore the name (of the function template) cannot be found via unqualified lookup. – dyp Mar 07 '14 at 20:13
  • @dyp Hmm. So if I put it in a `namespace detail` with a toy `struct detail::Foo` argument, it would work? – Yakk - Adam Nevraumont Mar 09 '14 at 16:08
  • I think so. I've answered a question relating to this issue some months ago, I'll see if I can find it. – dyp Mar 09 '14 at 16:14
  • Hmm seems like [this](http://stackoverflow.com/q/18493826/420683) was (one) of the questions I had in mind. Doesn't cover your workaround, though. – dyp Mar 09 '14 at 16:26