I was wondering if there was a way to specialize a template in the following way:
template<typename... Ts>
class Typelist { };
template<template<typename> typename... TTs>
class Typelist<TTs<typename>> { }; //I don't know if that is the right syntax, at least the compiler doesn't complain
I want it to work as a list of templated types as well as a list of non-templated types:
template<typename T>
class AT {};
template<typename T>
class BT {};
template<typename T>
class CT {};
int main() {
using tl1 = Typelist<int, float, double>; //works fine
using tl2 = Typelist<AT, BT, CT>; //gives an error
}
Edit:
If I declare the secont Typelist as a seperate type it works...
template<template<typename> typename... TTs>
class Typelist2 { };
//...
using tl2 = Typelist2<AT, BT, CT>; //compiler doesn't complain and it works fine
I was wondering though if it was possible to use only Typelist for both cases so that Typelist2 doesn't have to be a seperate type.
Can anybody help me?
I was wondering though if it was possible to use only Typelist for both cases so that Typelist2 doesn't have to be a seperate type.
I don't think so.
Because TypeList is defined as template<typename... Ts> or template<template<typename> typename... TTs>; both definition can't work togheter.
The best I can imagine to help you is define a TypeList base version for simple types
template <typename ... Ts>
struct TypeList
{
// here you can use Ts...
};
and a specialization for containers (with only a type in it) as follows
template <template <typename> class ... Tts, typename ... Ts>
struct TypeList<Tts<Ts>...>
{
// here you can use Ts... and Tts...
};
where you can use Ts and Tts.
But isn't a great solution because you can't define a containers TypeList simply as
TypeList<AT, BT, CT> tcl;
but you have to add contained dummy (?) types as follows
TypeList<AT<int>, BT<float>, CT<double>> tl2;
Another problem is you can't mix they, so
TypeList<AT<int>, BT<float>, double> tl;
call the base version (no containers) of TypeList.
Related
I was wondering whether it's possible to make a list containing template template parameters, like
template <
template <typename...> class TTP0,
template <typename...> class... TTPs
>
struct TTP_List : TTP_List<TTPs...> {};
A problem I encountered is that I did not know a good way to access the elements of the list, that is, TTP0. I would like to use type aliases, typedef or using. I however know this is not possible, because the template template parameters are not types and must therefor not be treated as such.
A approach I could imagine working is making explicit structs to read the data and make it use specializations, such as:
template <template <typename...> class>
struct container_TTPs;
template <template <typename...> class TTP>
struct container_TTPs<std::vector> {};
However, this approach seems very explicit. Is there a way to accomplish this recognition without this use of template specialization?
Feel free to ask if I need to elaborate.
EDIT: For example, I want to be able to use certain expressions for every held type, such as TestClass<TTP_List<std::vector, std::list>>::value, where TestClass uses the std::vector and the std::list, without requiring a variadic template within TestClass, so that multiple TTP_Lists can be passed.
I don't understand what do you mean with "access the elements of the list".
It seems to me that you should give us an example of what do you want, concretely, do accessing elements of the list.
Anyway, as you can use using to "access" (?) typenames
template <typename T0, typename ... Ts>
struct foo
{
using type = T0;
};
you can use a template using to "access" (?) a template-template parameter as follows
template <template <typename...> class T0,
template <typename...> class ... Ts>
struct foo
{
template <typename ... As>
using templ_type = T0<As...>;
};
and you can use it in this way
// vi is a std::vector<int>
foo<std::vector, std::set, std::map>::templ_type<int> vi { 0, 1, 2 };
The problem (a problem) is that a template parameter variadic list (isn't important if of typenames, of values or of template-templates) must be in last position.
So
template <typename ... Ts, typename T0>
struct foo
{ };
is wrong, because Ts... must be in last position, and
template <typename T0, typename ... Ts>
struct foo
{ };
is correct.
With template-template parameters,
template <template <typename ...> class ... Ts,
template <typename ...> class T0>
struct foo
{ };
is wrong where
template <template <typename ...> class T0,
template <typename ...> class ... Ts>
struct foo
{ };
is correct.
I was wondering how to emulate the following:
template<class> struct foo;
template<template<class..., int..., class...> class list,
class... clist1, int... ilist1, class... clist2>
struct foo<list<clist1..., ilist1..., clist2...>> {
};
This specialization (hypothetically) accepts a class with any number of classes, then integers, then classes. Currently there seems to be no way to directly implement this. (Bonus points if you can comment on why the standard doesn't support this)
An example of when this would be practical is in Eigen's linear algebra library where most classes are structures like:
Vector<class Scalar_type, int rows, class... options>
Mstrix<class Scalar_type, int rows, int cols, class... options>
With the above enabled, meta-template functions could be used that accept any of these base classes. Because it is not supported you have to write specializations for each class.
Is there any way to emulate a template function that supports accepting classes like the above?
I am looking for a generic solution. (Writing specializations for each class is not generic, and I am not directly looking for a solution to Eigen's library, that is just an example)
Example for clarification
Lets say I want to get the first class of a template class.
Somehow I get the original class type from some other meta-template function. Ergo I don't know what it's template parameters look like.
Maybe it's:
Vector1<class Scalar_type, int rows, class... others>
Or
Vector2<class Scalar_type, class... others>
Because I'm not directly using the type my meta template function must be of something like template<class> struct foo; with various specializations.
In this case getFront is a good example as I would need 2 specializations:
template<class> struct getFront;
template<template<class...,int...,class...> class param,
class... l1, int... l2, class... l3, class first>
struct getFront<param<first, l1..., l2... l3....> {
using type = first; };
and
template<template<class...> class param, class first, class... others>
struct getFront<param<first, others...>> {
using type = first;
};
Is there any way to emulate a template function that supports accepting classes like the above?
What about using template specialization as follows ?
template <typename...>
struct foo;
template <typename ... Ts1, int ... Is, typename ... Ts2>
struct foo<std::tuple<Ts1...>,
std::integer_sequence<int, Is...>,
std::tuple<Ts2...>>
{
};
Or, if you prefer parametrize the template containers, something like
template <template <typename...> class Ct1, typename ... Ts1,
template <int...> class Ci, int ... Is,
template <typename...> class Ct2, typename ... Ts2>
struct foo<Ct1<Ts1...>, Ci<Is...>, Ct2<Ts2...>>
{ };
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;
I am attempting to build a variadically templated class. As is common, each level of the instantiation needs to instantiate the "next level" by slicing off one type and then using the remainder. For my final level, rather than specialize on one type, I'd rather give some base case type and keep from duplicating the actual logic.
I've added a std::conditional to switch on the BaseCase when the rest of the types consists of an empty parameter pack.
class BaseCase { };
template <typename T, typename... Ts>
class VariadicClass;
template <typename... Ts>
using NextLevel = typename std::conditional<
sizeof...(Ts) != 0, VariadicClass<Ts...>, BaseCase>::type;
template <typename T, typename... Ts>
class VariadicClass {
T this_level; // whatever
NextLevel<Ts...> next_level; // fails when Ts is empty
};
The problem is that VariadicClass is templated on at least one type parameter, so when it hits the base case (Ts is empty), trying to use std::conditional uses VariadicClass<>, which fails of course.
The solution I've managed is to write some specific functions and use decltype along with overloads, and not use std::conditional at all.
template <typename... Ts>
VariadicClass<Ts...> type_helper(Ts&&...);
BaseCase type_helper();
template <typename... Ts>
using NextLevel = decltype(type_helper(std::declval<Ts>()...));
Now, this works, but if I want to keep up this practice every time I have a variadic class, it seems tedious. Is there a way to use std::conditional or something similar to achieve this effect without having to write out so much problem-specific code?
Defer evaluation.
template<class T>struct identity{
template<class...>using result=T;
};
template<template<class...>class src>
struct delay{
template<class...Ts>using result=src<Ts...>;
};
template <typename... Ts>
using NextLevel =
typename std::conditional<
sizeof...(Ts) != 0, delay<VariadicClass>, identity<BaseCase>
>::type::template result<Ts...>;
identity ignores the Ts... and returns its argument. delay takes a template and applies the Ts.... While the signature looks suspicious, it works.
Why not just
class BaseCase { };
template <typename... Ts>
class VariadicClass; // undefined base template
template <typename... Ts>
using NextLevel = typename std::conditional<
sizeof...(Ts) != 0, VariadicClass<Ts...>, BaseCase>::type;
template <typename T, typename... Ts>
class VariadicClass<T, Ts...> { // partial specialization for having at least 1 type parameter
T this_level; // whatever
NextLevel<Ts...> next_level;
};
After reading T.C.'s answer and Yakk's comment, I realized I could write this as one templated class with two specializations, rather than write another BaseClass and the type alias.
template <typename... Ts>
class VariadicClass;
// specialization gets everything but an empty Ts
template <typename T, typename... Ts>
class VariadicClass<T, Ts...> {
VariadicClass<Ts...> next_level;
// normal case
};
template <>
class VariadicClass<> { // instead of class BaseCase
// base case
};
Alternatively, you may specialize VariadicClass<T>
class BaseCase {};
// general case
template <typename T, typename... Ts>
class VariadicClass {
T this_level; // whatever
VariadicClass<Ts...> next_level;
};
// specialization
template <typename T>
class VariadicClass<T> {
T this_level; // whatever
BaseClass next_level;
};
I was writing some code where I have a class that can accept mixins as variadic template parameters. However, I also need the mixins to be able to access the base class through the CRTP idiom. Here's a minimal example that cannot quite do what I want:
template <template <class> class... Mixins>
class Foo : Mixins<Foo<Mixins...>>... {};
However, a mixin that I might pass to Foo will, in general, have several template parameters, like so:
template <class Derived, class Type1, class Type2>
class Bar
{
Derived& operator()()
{
return static_cast<Derived&>(*this);
}
};
How can I change Foo so that I can have it inherit from a number of base classes, where I control the template parameters accepted by each base class? If I hand Foo a list of template-template parameters, along with a list of arguments to pass to them, then I don't see how I would be able to associate each template-template parameter with its arguments. So far, I thought of something like this, but I don't know how I would proceed.
template <template <class...> class T,
template <class...> class... Ts>
class Foo : /* How do I retrieve the arguments? */
I am not quite sure I understood the problem, so please let me rephrase it so that we can start on the right foot.
You need to thread the derived type to the base classes, in a typical CRTP use case, while at the same time passing other template parameter to the various base classes.
That is, a typical base class will be:
template <typename Derived, typename X, typename Y>
struct SomeBase {
};
And you want need to create your type so that you can control the X and Y and at the same time pass the complete Derived class.
I think I would use the apply trick to generate the base class on the fly, from an adapter provided in the argument list of the Derived class.
template <typename Derived, typename X, typename Y>
struct SomeBase {};
template <typename X, typename Y>
struct SomeBaseFactory {
template <typename Derived>
struct apply { typedef SomeBase<Derived, X, Y> type; };
};
// Generic application
template <typename Fac, typename Derived>
struct apply {
typedef typename Fac::template apply<Derived>::type type;
};
Then, you would create the type as:
typedef MyFoo< SomeBaseFactory<int, float> > SuperFoo;
Where Foo is defined as:
template <typename... Args>
struct Foo: apply<Args, Foo<Args...>>::type... {
};
And just because it's been a while since I trudged so deeply in templates, I checked it worked.
Of course, the Factory itself is not really a specific to a given type, so we can reuse the wrapper approach you had experimented:
template <template <typename...> class M, typename... Args>
struct Factory {
template <typename Derived>
struct apply { typedef M<Derived, Args...> type; };
};
And yes, it works too.
If I understand your question correctly, you should create template aliases that reduce each mixin to a single template parameter.
template <typename Derived>
using BarIntFloat = Bar<Derived, Int, Float>;
template <typename Derived>
using BazQux = Baz<Derived, Qux>;
typedef Foo<BarIntFloat, BazQux> MyFoo;
Here's a solution I came up with. There may be a more elegant way to do this, but I couldn't think of any. One caveat is that all of the mixins used need to first be nested in the wrapper struct, along with their respective arguments.
template <template <class...> class Mixin, class... Args>
struct wrapper
{
typedef Mixin<Args...> type;
};
template <class... Args>
struct test
{
};
template <class Arg, class... Args>
struct test<Arg, Args...> : Arg::type, test<Args...>
{
};
template <class T>
class mixin1 {};
template <class T1, class T2>
class mixin2 {};
template <class T1, class T2, class T3>
class mixin3 {};
int main()
{
test<wrapper<mixin1, int>, wrapper<mixin2, int, float>> foo;
return 0;
}
#void-pointer
This is basic omission of variadic templates. User cannot get i-th type from T... or get i-th value from values...
Here is a link from going native 2012 lecture by Andrei Alexandrescu:
template <typename... Ts>
void fun(const Ts&... vs) {}
• Ts is not a type; vs is not a value!
typedef Ts MyList; // error!
Ts var; // error!
auto copy = vs; // error!
So Ts/vs should be some kind of tuple.