reference variadic template parameter pack from another template - c++

I have a variadic template class that defines collection of types
template <typename ... Types> class TypePack { };
Which is instantiated several times
typedef TypePack<T1, T2, T3> Pack1;
typedef TypePack<T1, T2, T4> Pack2;
I want to reference TypePack parameters from other templates
template <typename Pack> Client {
static constexpr std::array<Foo, sizeof...(Pack::Types)> foos {
make_foo<Pack::Types>()...
};
};
typedef Client<Pack1> Client1;
typedef Client<Pack2> Client2;
The code above is clearly wrong and doesn't compile. It just serves as illustration of what I would like to achieve.
I could define Pack1 and Pack2 through macros but I have a feeling that it should be possible to do it with variadic templates in C++14

What you're looking for is partial specialization:
template <typename Pack> struct Client;
template <class... Ts>
struct Client<TypePack<Ts...>>
{
static constexpr std::array<Foo, sizeof...(Ts)> foos {{
make_foo<Ts>()...
}};
};
// don't forget the definition
template <class... Ts>
constexpr std::array<Foo, sizeof...(Ts)> Client<TypePack<Ts...>>::foos;

Related

Metafunction to extract argument parameter lists from multiple functions pointers

For a single function it is possible to extract its parameter types like this:
template <class T>
struct Foo;
template <class Ret, class... Args>
struct Foo<Ret(*)(Args...)> { /* stuff */ };
Would it be possible to do the same for a series of function pointers? That is,
to be able to extract the arguments and then redeploy them in the same way? E.g. something like:
template <class.. T>
struct Foo;
template <class... Rets, class... Args>
struct Foo<Rets(*)(Args...)...> // I wish this worked
{
std::tuple<Rets(*)(Args...)...> fns; // Ditto
}
Late to the party, but this might be useful. First let's define some utilities:
template <class... T>
using void_t = void;
template <bool...> struct bool_pack;
template <bool... v>
using all_true = std::is_same<bool_pack<true, v...>, bool_pack<v..., true>>;
Then a metafunction to check whether a type is a function pointer:
template <class F>
struct is_function_pointer : std::integral_constant<bool, false> { };
template <class Ret, class... Args>
struct is_function_pointer<Ret (*)(Args...)> : std::integral_constant<bool, true> { };
Using these, let's write the class. The SFINAE toggle is placed first because the variadic pack takes up the right side:
template <class = void_t<>, class... T>
struct Foo_impl;
template <class... FuncPtrs>
struct Foo_impl<
std::enable_if_t<all_true<is_function_pointer<FuncPtrs>{}...>{}>,
FuncPtrs...
> {
std::tuple<FuncPtrs...> fns;
};
Finally, a typedef to hide the SFINAE toggle from the user:
template <class... T>
using Foo = Foo_impl<void_t<>, T...>;
VoilĂ ! Foo<void (*)(), int (*)(double)> goes to the specialization of Foo_impl which contains the adequate tuple, Foo<int, double> goes to the main template.
See it live on Coliru

Throw multiple-template class in a template template parameter - template binding?

Given the following class:
template <class T, template <typename> class B>
class A { B<T> b; };
I can now write code like such:
A<float, MyVector> a1;
A<int, MySet> a2;
What is the most elegant way to put multi-parameter classes of which all parameters are specified except one, in B? Like a map with int-keys? The only thing I can come up with is this:
template <class U> using C = MyMap<int, U>;
A<float, C<int>> a3;
Is there such a template equivalent to std::bind, where we can provide only a part of the parameters and leave one of them open? I'm quite sure the language doesn't provide for this, but people must've solved this before.
A<float, MyMap<int, _>> a3;
There isn't a built-in template equivalent to std::bind, but you can write one yourself. Here's a simple version which binds the first template argument which you could extend to suit your needs:
template <typename T, template <typename...> class B>
struct bind_t1 {
template <typename... Ts>
using type = B<T,Ts...>;
};
Then you just use bind_t1 like so:
A<float, bind_t1<int, std::map>::type> a3;
Note that for your example, you'll need to modify your template parameters to take a variadic template template:
template <class T, template <typename...> class B>
class A { B<T> b; };
Here's a slightly extended version which can bind a number of contiguous elements at the start of the parameter list:
template <template <typename...> class B, typename... Ts>
struct bind_nt1 {
template <typename... Us>
using type = B<Ts...,Us...>;
};
//Usage
A<std::less<int>, bind_nt1<std::map, int, float>::type> a3;
Here's a generic version based on the way std::bind does things. It doesn't do any validation and probably has some edge cases, but it's a good starting point. Thanks to Piotr Skotnicki for improvements.
template <std::size_t N>
struct placeholder{};
template <template <typename...> class B, typename... Ts>
struct bind_t {
private:
template <typename T, typename UTuple>
struct resolve_placeholder {
using type = T;
};
template <std::size_t N, typename UTuple>
struct resolve_placeholder<placeholder<N>, UTuple> {
using type = typename std::tuple_element<N-1, UTuple>::type;
};
public:
template <typename... Us>
using type = B<typename resolve_placeholder<Ts, std::tuple<Us...>>::type...>;
};
//Usage
A<int, bind_t<std::map, float, placeholder<1>, std::less<float>>::type> a3;
Using this, you can even change the order of template parameters:
//std::map<int,float>
bind_t<std::map, placeholder<2>, placeholder<1>>::type<float, int> b;

Variadic templates of Variadic templates class in c++

given Variadic templates data structure as below ( code from Eli Bendersky's website):
template <class... Ts> struct tuple {};
template <class T, class... Ts>
struct tuple<T, Ts...> : tuple<Ts...> {
tuple(T t, Ts... ts) : tuple<Ts...>(ts...), tail(t) {}
T tail;
};
we are able to define something like
tuple<double, uint64_t, const char*> t1(12.2, 42, "big");
Then how to define a template structure that could accept following signature?
Foo<tuple<int,double>, tuple<double,int,long> ..., tuple<std::string>> foo;
I think it would be like this:
template<tuple<class... Ts>... Tuples>
struct VariadicTuples {};
but it cannot compile. is that because the class in the Variadic templates cannot be Variadic templates? If so, How to make this work?
You simply cannot write that, syntactically. What would Ts hold in that situation? It would be different for each type in Tuples so it wouldn't really be usable.
What you can do instead is take advantage of Columbo's bool_pack trick:
template <bool...> struct bool_pack;
template <bool... v>
using all_true = std::is_same<bool_pack<true, v...>, bool_pack<v..., true>>;
To simply static_assert that all the Tuples are, in fact, tuples and then have VariadicTuples be a simple variadic class template:
template <typename > struct is_a_tuple : std::false_type { };
template <typename... T> struct is_a_tuple<tuple<T...>> : std::true_type { };
template <typename... Tuples>
struct VariadicTuples {
static_assert(all_true<is_a_tuple<Tuples>::value...>::value, "!");
};

Find template type of a template type c++

I would like to have a function that can take many different things (for simplicity) like so:
template <typename T>
typename type_to_return<T>::type // <-- Use type_to_return to get result type
foo(T t)
{
return typename type_to_return<T>::type(T); // <-- Build a thing!
}
I would then specialize the type_to_return class for the types I have created. This would make the entry be one function and I could then just define new type_to_returns and constructors.
I want type_to_return<T>::type to be just T if T is not some class template. Otherwise I want it to be that class's first template parameter. So for int, I get back int, and for MultOp<float,int,double>, I want to get back float.
How do I do that? I think I need to do something like:
// Base version
template <typename T>
struct type_to_return
{
typedef T type;
};
// Specialized type
template <template <typename> class T>
struct type_to_return<T <any_type_somehow> >
{
typedef template boost::magic_type_unwrapper<T>::param<1>::type type;
};
You may implement a type_unwrapper as follow:
template <typename T>
struct type_unwrapper;
template <template <typename...> class C, typename... Ts>
struct type_unwrapper<C<Ts...>>
{
static constexpr std::size_t type_count = sizeof...(Ts);
template <std::size_t N>
using param_t = typename std::tuple_element<N, std::tuple<Ts...>>::type;
};
which works as long there is no template value as in std::array<T, N>.
Note also that stl container declare some typedef to retrieve there template arguments as std::vector<T, Alloc>::value_type which is T.

C++ Template Template Instantiation

I have the following encapsulation code for variadic parameter packs.
template <typename... Args>
struct pack
{
};
template <template <typename... Args> class ENCAP, typename... Args>
struct encapsulate_arguments
{
typedef pack<ENCAP<Args>...> type;
};
template <template <typename... Args> class ENCAP, typename... Args>
struct encapsulate_arguments<ENCAP, pack<Args...>>
{
typedef pack<ENCAP<Args>...> type;
};
template <typename L>
struct Master
{
template <typename T>
struct Slave
{
typedef T type;
};
};
This works fine for encapsulating variadic packs such as:
typedef encapsulate_arguments<Master<float>::Slave, double, int>::type foo;
or
typedef encapsulate_arguments<Master<float>::Slave, pack<double, int>>::type foo;
or
typedef encapsulate_arguments<std::vector, pack<double, int>>::type foo;
where it is not dependent on another template parameter - resulting in the following being defined :
pack<Master<float>::Slave<double>, Master<float>::Slave<int>>
or
pack<std::vector<double>, std::vector<int>>
The problem is that if I want to make the encapsulation template parameter ENCAP type dependent I can't get it to compile:
template <typename L>
struct Other
{
// ARGGH!!!
// typedef encapsulate_arguments<Master<L>::Slave, pack<double, int>>::type EmbeddedType;
};
http://ideone.com/ZwfVaU
Is this even possible and / or how can I make this work?
You're missing a typename and a template:
typedef typename encapsulate_arguments<
// ^^^^^^^^
Master<L>::template Slave, pack<double, int>
// ^^^^^^^^
>::type EmbeddedType;
Demo