From: PGK on
In the class "Foo" below, is it possible to use a constructor
initialization list to initialize "cs", a tuple of complex values?

// #include <iostream>,<tuple>,<complex>,<type_traits>

template <typename T, typename ... Ts>
struct Foo {
std::tuple<std::complex<T>, std::complex<Ts>...> cs;

template<typename ... Us>
Foo(T c1, T c2, Us ... ts) : ???? { }
};

int main(int argc, char *argv[]) {
Foo<int,bool,double> a(1,2,true,false,42.0,43.0); // For example
}

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Daniel Krügler on
On 15 Mrz., 12:35, PGK <graham.k...(a)gmail.com> wrote:
> In the class "Foo" below, is it possible to use a constructor
> initialization list to initialize "cs", a tuple of complex values?
>
> // #include <iostream>,<tuple>,<complex>,<type_traits>
>
> template <typename T, typename ... Ts>
> struct Foo {
> std::tuple<std::complex<T>, std::complex<Ts>...> cs;
>
> template<typename ... Us>
> Foo(T c1, T c2, Us ... ts) : ???? { }
> };
>
> int main(int argc, char *argv[]) {
> Foo<int,bool,double> a(1,2,true,false,42.0,43.0); // For example
> }

[It is unspecified whether std::complex can be instantiated
with something else than a floating point type].

Try the following:

#include <cstddef>
#include <complex>
#include <tuple>

template<std::size_t...>
struct indices{};

template<std::size_t I, class Indices, class Tuple, std::size_t N>
struct pack_impl;

template <std::size_t I, std::size_t... Indices, class Tuple,
std::size_t N>
struct pack_impl<I, indices<Indices...>, Tuple, N>
{
typedef pack_impl<I + 1, indices<Indices..., 2 * I>, Tuple, N>
Next;
typedef typename Next::index_values index_values;
typedef typename Next::return_type return_type;
};

template <std::size_t N, std::size_t... Indices, class Tuple>
struct pack_impl<N, indices<Indices...>, Tuple, N>
{
typedef indices<Indices...> index_values;
typedef std::tuple<std::complex<typename std::tuple_element<
Indices, Tuple>::type>...> return_type;
};

template<std::size_t Index, class Tuple>
inline std::complex<typename std::tuple_element<Index, Tuple>::type>
make_complex(const Tuple& ts) {
return std::complex<typename std::tuple_element<Index,
Tuple>::type>(
std::get<Index>(ts), std::get<Index + 1>(ts));
}

template<class Result, std::size_t... Indices, class Tuple>
inline Result make_complex_tuple(indices<Indices...>, const Tuple& ts)
{
return Result(make_complex<Indices>(ts)...);
}

template<class... Types>
struct pack {
static_assert((sizeof...(Types) & 1) == 0, "variadic parameter
number must be even");
typedef pack_impl<0, indices<>, std::tuple<Types...>, sizeof...
(Types)/2> Impl;
typedef typename Impl::return_type return_type;
typedef typename Impl::index_values index_values;
static return_type make(const Types&... ts) {
return make_complex_tuple<return_type>(index_values(),
std::make_tuple(ts...));
}
};

template <typename T, typename ... Ts>
struct Foo {
private:
std::tuple<std::complex<T>, std::complex<Ts>...> cs;

public:
template<typename... U,
typename = typename std::enable_if<
sizeof...(U) == 2 * sizeof...(Ts)>::type>
Foo(T t1, T t2, U... us) : cs(pack<T, T, U...>::make(t1, t2,
us...))
{
}
};

int main() {
float f = 12.1;
double d = 3.14;
long double ld = 0.0;
typedef Foo<double> F1;
F1 x1(d, d);
typedef Foo<float, double> F2;
F2 x2(f, f, d, d);
typedef Foo<float, double, long double> F3;
F3 x3(f, f, d, d, ld, ld);
}

HTH & Greetings from Bremen,

Daniel Kr�gler



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: PGK on
Thanks Daniel. I've assembled a different solution with the intention
to use decltype and auto, as well as tuple_cat for a recursive
construction. Check it out:

template <int I, int N, typename... Us>
struct cmplx_helper {
static auto cmplx (tuple<Us...> t)
-> decltype (tuple_cat(
make_tuple(complex<typename tuple_element<I,decltype
(t)>::type>
(get<I>(t),get<I+1>(t))),
cmplx_helper<I+2,N,Us...>::cmplx(t))) {
return tuple_cat(
make_tuple(complex<typename tuple_element<I,decltype
(t)>::type>
(get<I>(t),get<I+1>(t))),
cmplx_helper<I+2,N,Us...>::cmplx(t));
}
};

template <int N, typename... Us>
struct cmplx_helper <N,N,Us...> {
static tuple<> cmplx(tuple<Us...> t) { return tuple<>(); }
};

template <typename... Us>
auto tuple_cmplx (tuple<Us...> t)
-> decltype
(cmplx_helper<0,tuple_size<tuple<Us...>>::value,Us...>::cmplx(t)) {
return
cmplx_helper<0,tuple_size<tuple<Us...>>::value,Us...>::cmplx(t);
};

template <typename... Ts>
class Foo {
public:

tuple<complex<Ts>...> cs;

template <typename... Us,
typename = typename std::enable_if<
sizeof...(U) == 2 * sizeof...(Ts)>::type>
Foo(Us... us) : cs(tuple_cmplx(tuple<Us...>(us...))) {}
};

int main(int argc, char *argv[])
{
Foo<bool,int,double> q(true,false,1,2,3.5,4.5);
return 0;
}

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Thomas Petit on
On 23 mar, 15:05, PGK <graham.k...(a)gmail.com> wrote:
> Thanks Daniel. I've assembled a different solution with the intention
> to use decltype and auto, as well as tuple_cat for a recursive
> construction. Check it out:
>
> // code...
>

Impressive !

But I don't get why you pass a list of single element instead of
passing a list of std::pair.
It makes the implementation so much simpler...
And with intializer lists the calling point is quite elegant as well :

#include <tuple>
#include <complex>
#include <utility>

template <typename... Ts>
struct Foo {
std::tuple<std::complex<Ts>...> cs;
Foo(std::pair<Ts, Ts>... ts) : cs(std::complex<Ts>(ts.first,
ts.second)...){}
};

int main(int argc, char *argv[])
{
Foo<bool,int,double> foo( {true, false} , {1, 2} , {3.5, 4.5} );
return 0;
}

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: PGK on
Hi Thomas,

> Impressive !
>

Thankyou.

> But I don't get why you pass a list of single element instead of
> passing a list of std::pair.


I would love to be able to choose that solution, but the
interface I am faced with is already defined (to use single elements).

Graham

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]