In C++ there are 2 template types (to my knowledge): template classes and template functions. Why is it not possible to have a template of template? (be it class, or function, or other template). Has it ever been considered in standards? Does it break C++ syntax/spirit in a way?
I know it may sound crazy, and it's easy to get around.
What is possible with C++:
template<bool b>
class TemplateDependingOnBool
{
public:
template<typename T>
class TheTemplateWeWant{};
}
What would be great:
template<bool b>
template<typename T>
class TheTemplateWeWant{};
and call it in a policy-based style (that's where it's really interesting):
template<typename T, template<typename> class ThePolicy = TheTemplateWeWant<true> >
class Foo {};
The way it's possible to do now is to use:
template<typename T,
template<typename> class ThePolicy = TemplateDependingOnBool<true>::TheTemplateWeWant >
class Foo{};
which is not very elegant.
EDIT:
I know I can template on 2 parameters. The goal is to use the underlying template class (the templated template) as something by itself, be it in a template alias or a template template parameter (as shown in my example).
Policy-based design is a reference to Andrei Alexandrescu's Modern C++ Design, which is the main reason why the feature I'm asking might be useful (because templates are used as template parameters).
With C++11, you're wrong in assuming only two types of templates. There are also type aliases which allow
template <bool b, typename T>
class TheTemplateWeWant { ... };
template<typename T>
using ThePolicy = TheTemplateWeWant<true, T>
If I'm understanding what you're asking correctly (and I'm not entirely clear on your question), then you could write your template taking two parameters:
template <bool b, typename T>
class TheTemplateWeWant { ... };
add a metafunction to partially apply the bool:
template <bool b>
struct PartiallyWant {
template <typename T>
using type = TheTemplateWeWant<b, T>;
};
and then pass that as your policy:
template<typename T,
template<typename> class ThePolicy = PartiallyWant<true>::type >
class Foo { ... };
Foo<char, PartiallyWant<false>::type> foo;
So why not just layer the templates like you propose? The simple answer is that there's no reason to. If TheTemplateWeWant has two template parameters (bool b and typename T, regardless of whether it's an "inner" class or not), then we should express it as such. And if we want to only apply one type or the other, that's something that has fewer use-cases than a general template while also being solvable with just a few lines of boilerplate. Additionally, what if we had such a feature, and now I want to partially apply the T instead of the b? With a few lines of boilerplate I can again accomplish the same thing, but with the layering this would be impossible.
As far as i know you cand you simply that, and it works just as you want - class templated with 2 parameters.
template<bool b, typename T>
class TheTemplateWeWant{}; //valid in C++
What you're describing is partial binding of template parameters, just like std::bind can turn a binary function into a unary function.
For metaprogramming madness, there's Boost.MPL. They do have a template boost::mpl::bind.
Related
I'm new in advanced usage of templates and concepts, so here is a liitle bit complex problem:
I have some Traits concept of many traits for each of Source classes:
template<typename _Traits>
concept Traits = requires
{
std::same_as<std::decay_t<decltype(_Traits::token)>, std::string_view>;
};
I have some template class that uses this concept to handle object_one with various traits (for example, half of Source classes returns object_one):
template <concepts::Traits _Traits>
class Object_one_handler final
{
static std::string handle_object(const object_one& obj) {/*...*/}
};
Then I have Objects_handlers concept of handlers for various objects from set {object_one, object_two, object_three} from various Sources with their Traits:
template<template <concepts::Traits _Traits> class _Objects_handlers, typename _Object>
concept Objects_handlers = requires(const _Object& obj)
{
// has handle_object method
{ _Objects_handlers<???????>::handle_object(obj) } -> std::same_as<std::string>;
};
Finally, I creating some database with specified as template parameter Object_handler:
template<concepts::Objects_handlers _handler>
class database
{...};
(Actually all of concepts have additional requirements, but it doesn't matter here)
So problem is in last Objects_handlers concept:
template<template <concepts::Traits _Traits> class _Objects_handlers, typename _Object>
concept Objects_handlers = requires(const _Object& obj)
{
// has handle_object method
{ _Objects_handlers<???????>::handle_object(obj) } -> std::same_as<std::string>;
^^^^^^^
};
I can't check _Objects_handlers method without template parameter (obviously) and I can't properly set the template parameter which must be one of Traits.
How can I do that?
And actually it may be problem in usage of Objects_handlers in template of database class, so one more question: how to use it?
P.S. It can be XY problem or not about concepts at all... Maybe composition with strategy pattern will be more usefull, but still want try to create this maybe useless, but workable concept.
Let's reduce this problem a lot.
template <typename T>
struct C {
void f();
};
Now, your goal is to write a concept that takes any class template (e.g. C) and checks that every specialization of it has a nullary member function named f.
template <template <typename> class Z>
concept HasF = requires (Z<???> z) {
z.f();
};
The problem is - class templates in C++ just don't work like this. Even for a particular class template, like C, you can't require that every specialization has f. There's no way to ensure that like somebody, somewhere, didn't add:
template <> struct C<std::vector<std::list<std::deque<int>>>> { };
All you can do is check that a specific type has a nullary member function named f. And that's:
template <typename T>
concept HasF = requires (T t) { t.f(); };
The type-constraint syntax, template <Concept T>, is only available for concepts that constrain types, not concepts that constrain templates or values.
I've been learning the concept of SFINAE in C++ recentlly and I am currentlly trying to use it in a project.
The thing is, what I'm trying to do is different than anything I could find, and I can't figure out how to do it.
Let's say I have a template class called MyParent:
template <typename Elem>
class MyParent;
And a non-template class called MyClass, that inherites it, using char as Elem:
class MyClass : public MyParent<char>;
Now, I want to use SFINAE in order to check if a typename inherites MyParent, regardless of what Elem type is used.
I can't use std::is_base_of, because of the parent's template.
I've tried to do the following:
template <typename T>
struct is_my_parent : std::false_type {};
template <typename Elem>
struct is_my_parent<MyParent<Elem>> : std::true_type {};
Now, if I check for is_my_parent<MyParent<Elem>>::value, it gives me true. Which is good.
However, when I check for is_my_parent<MyClass>::value, I recive false. Which kind of makes sence because MyClass isn't actually MyParent<Elem>, but I didn't manage to get what I wanted.
Is there any convenient way to achive such a thing in C++, other than defining is_my_parent for each and every class that inherites from MyParent?
You might do
template <typename T>
std::true_type is_my_parent_impl(const MyParent<T>*);
std::false_type is_my_parent_impl(const void*);
template <typename T>
using is_my_parent = decltype(is_my_parent_impl(std::declval<T*>()));
Demo
Is there any convenient way to achive such a thing in C++, other than defining is_my_parent for each and every class that inherites from MyParent?
There is, but you'll need to use more elaborate meta-programming techniques. Go entirely back to basics, as it were.
template <class C>
class is_my_parent {
using yes = char;
using no = char[2];
template<typename t>
static yes& check(MyParent<t> const*);
static no& check(...);
public:
enum { value = (1 == sizeof check(static_cast<C*>(0))) };
};
It relies on two basic properties of function overloading and templates:
A derived class can be used to match a function template that takes a base class template as an argument.
Ellipsis offer a conversion sequence that is always considered worse than any other.
Then it's just a matter of inspecting the return type of the chosen overload to determine what we got. Other than the type alias, you can even use this in C++03. Or you can modernize it, so long as overload resolution does the work for you, the check will be performed just the same.
I like Jarod42's answer much better, but an actual SNINAE approach somewhat close to your attempt can work. Here's what I came up with.
To use the type_traits to answer this, we need to know the type of the element. We can make MyParent expose it:
template <typename Elem>
class MyParent {
public:
using ElemType = Elem;
};
Then the default (false) is_my_parent takes an extra arg and the void_t technique* can be used:
template <typename T, typename = void>
struct is_my_parent : std::false_type {};
template <typename T>
struct is_my_parent<T, std::void_t<typename T::ElemType>> :
std::is_base_of<MyParent<typename T::ElemType>, T>::type {};
The specialization is only valid if ElemType is an accessible type in T, and then it results in std::true|false type if the inheritance relationship holds.
live example: https://godbolt.org/z/na5637Knd
But not only is the function overload resolution a better approach for simplicity and size, it will also compile much faster.
(*) void_t was exposed to the world in this fantastic 2-part 2014 talk by Walter Brown. Recommended even if only for review.
https://www.youtube.com/watch?v=Am2is2QCvxY
First, I have a template class:
template <typename T>
class Component;
Then I would like to create a class that can hold an arbitrary set of Component<T>'s as members, e.g. for N=2:
template <typename T, typename U>
class Aggregate
{
private:
Component<T>* m_comp1;
Component<U>* m_comp2;
};
At first glance, this looks like using variadic template would be a natural application.
template <typename... Comps>
class Aggregate
{
// what should go here for me to get Component<Comp1>, Component<Comp2>, ...?
};
However, I am unable to write the code that would essentially allow me to go from T, U, ... -> C<T>, C<U>, .... Currently, I have this achieved by creating a partial specialization for each N=1,2,3,4,... case, but this yields a lot of duplicated boilerplate code (and I would like to avoid having to write the Aggregate class to take in the template parameters directly as <Comp<T>,Comp<U>,...>). Is there a way to achieve the above? Thank you for any feedback/help in advance.
try using a tuple:
template <typename... Comps>
using Aggregate = std::tuple<Component<Comps>*...>;
There's no simple solution. Use std::tuple. Otherwise you'd need to reimplement it yourself, which is not trivial.
A class ExpectTTs takes a number of template template parameters:
template< template<typename> class... TT >
struct ExpectTTs {};
Another type requires two template parameters. I need to fix one and pass the rest to ExpectTTs.
Currently I'm using this solution:
template< typename T >
struct TwoTs {
template< typename U >
struct Inner {};
};
ExpectTTs< TwoTs<int>::Inner >
Is it possible to change something so that I can pass a simple template instantiation like TwoTs<int> to ExpectTTs?
In several points in my codebase I have expressions like ExpectTTs< A, B, C<int>::Inner, D, E<int,int>::Inner, F<void>::Inner > and it seems unnecessary hard to read and write.
Any C++ version is fine.
If you have a template taking two parameters you cannot only specify one and obtain a template template. That is simply not possible. You also cannot create a template template alias as you can create a template alias with using. C++ does not make it easy to work with template templates, you can basically only use them when you fully instantiate them or when you pass them as a parameter to a template.
You also cannot get ExpectTTs really working with both template template parameters and type template parameters, since C++ strictly distinguishes between them (otherwise you could do something like let ExpectTTs extract the inner type). Maybe you could let ExpectTTs only take type template parameters, and make also A, B, and D have an Inner template while themselves being types, so you can let ExpectTTs always do the work for extracting the Inners. But then of course, you wouldn't be able to pass STL-templates like std::optional directly.
One small thing you could (in my opinion) improve in your design is using something like this:
#include <utility> // For the example
#include <optional>
template<template<class> class...>
struct ExpectTTs {};
template<template<class...> class TT, class T>
struct bind {
template<class U>
using bound_t = TT<T, U>;
};
ExpectTTs<std::optional, bind<std::pair, int>::bound_t> e{};
It's maybe even more verbose, but it does not need the intrusive Inner type and returns exactly the template template you want and not some other stand-in.
Say I have a template class like so:
template < typename TParam >
class Test
{
// content
};
I want to pull out the first template parameter of TParam if it's a specialization of a class template. Something like:
template < typename TParam >
class Test
{
using TParamInner = TemplateType<TParam>::Type;
// use TParamInner here
};
Additional info:
I have access to all of C++98.
I have access to a subset of C++11.
I would prefer to avoid the stdlib if possible (assume this is
because I'm using an embedded system for which no stdlib is available and/or because I am heavily memory-constrained)
You can get close with something like:
template <class >
struct first_template_param;
template <template <class...> class Z, class T, class... Ts>
struct first_template_param<Z<T, Ts...>> {
using type = T;
}
It won't handle std::array or any other class templates that take non-type template parameters. But it'll handle all the "normal" class templates. You can always then add extra specializations for all the ones you want:
template <class T, size_t N>
struct first_template_param<std::array<T,N>> {
using type = T;
}
Thanks to #Barry for spurring the solution along.
It's not a complete answer for all template types, but it works for templates where all parameters are types, which is a large number of the most useful templates.
template < typename Head, typename ... Tail >
struct split { using first = Head; };
template <class >
struct cls_template_info; // fails on non-templates
template <template <class...> class Z, class... Ts>
struct cls_template_info<Z<Ts...>>
{
using type = typename split<Ts...>::first; // typename used to disambiguate
};
This can then be used as using T = cls_template_info<std::vector<int>>::first;.
You can't. A template type is never carried up to runtime. You have to instantiate it (this leads to a complete new type), and the compiler then generates the needed code to make it appear as if you have defined specifically for the type parameters you specified. Indeed, in old compilers (this has been solved a lot of time ago) when you instantiate a generic type in several compilation units, that lead to several repetitions of the same code in the final program. But as I've said, this has been solved time ago.