C++ Weekly - Ep 368 - The Power of template-template Parameters: A Basic Guide

preview_player
Показать описание
☟☟ Awesome T-Shirts! Sponsors! Books! ☟☟

Upcoming Workshop: Applied constexpr: The Power of Compile-Time Resources, C++ Under The Sea, October 10, 2024

T-SHIRTS AVAILABLE!

WANT MORE JASON?

SUPPORT THE CHANNEL

GET INVOLVED

JASON'S BOOKS

► C++23 Best Practices

► C++ Best Practices

JASON'S PUZZLE BOOKS

► Object Lifetime Puzzlers Book 1

► Object Lifetime Puzzlers Book 2

► Object Lifetime Puzzlers Book 3

► Copy and Reference Puzzlers Book 1

► Copy and Reference Puzzlers Book 2

► Copy and Reference Puzzlers Book 3

► OpCode Puzzlers Book 1


RECOMMENDED BOOKS

AWESOME PROJECTS

O'Reilly VIDEOS

Рекомендации по теме
Комментарии
Автор

For anyone who is stuck in C++17 and doesn’t know, you can totally do this design by introspection in C++, it’s just more of a hassle.

You’d need a purpose-made detector metafunction, like such:

template<typename T, typename = void>
struct has_reserve : std::false_type {};

template<typename T,
typename = std::void_t<

struct has_reserve : std::true_type {};

template<typename T>
constexpr inline bool has_reserve_v =
has_reserve<T>::value;

Then you can:

if constexpr {
// …
}

ultradude
Автор

I’ve had some fun with template template parameters and higher-order metafunctions

Though, it is a little unsettling seeing
`template<template<typename> typename… Functions>`.
Yes, that is a variadic pack of template template parameters, each expected to be a unary metafunction.

ultradude
Автор

The version without the allocator doesn't work in Clang.
I'm not sure why but for some reason Clang doesn't like containers with only a single template argument while GCC has no problem with it.

zamf
Автор

First off THANK YOU Jason. I dis an interview yesterday and was asked "how I keep up to date"..
I stated you were the best resource out there (along side Herb Sutter and Scott Meyers material). Your name in lights ;)

Ok, one question I was asked was "explain exactly what happens at stack and assembly when code like this is called;

Foo f = bar();

Where bar returns by value, say.

I'd love to see your perspective. I'm researching here. Disgusted I didn't know exact answer (though I was able to cite RVO, and that copy ctor is called instead of default ctor, then assignment).

I definitely "wobbled" at stack assembly level (though I realise f is pushed onto stack at invocation of foo and assigned the result of foo return. See..I'm vague already 😂😂

Any chance you could do a short video on this. It would give a leg up into digging deeper into stack and assembly behaviour.

Have a great day and thanks again for your videos. Best out there imho

grahamdd
Автор

The first time I saw something like this, I was baffled. It was used in a json library, where you could specify containers for objects and lists.

yato
Автор

Great episode - Thanks! I am still sometimes confused how "if constexpr (....)" and consteval are used for and how to use them in a good way. Did you maybe already do an episode about these topics that you can share?

ferdistapenhorst
Автор

Hi Jason, Thank you. What are your C++ read, watch, ....recommendations(books, vids, ...)?

eotcoldhymns
Автор

I guess `get_data()` could also use `requires` to require that `ResultType` has `emplace_back()`, or otherwise satisfies a "standard container" concept?

dwarftoad
Автор

I'm going to comment "higher-kinded types" for the algorithm. I like how painless it is in C++. Someone's gonna implement monad transformers on top of that.

vytah
Автор

Working with vectors in my homebrew engines, I came up with the convention of using * for dot products (a•b) and / for cross products (a×b). What policy will I need to ensure an operator overload is compiled only for 3D (or 7D) space? (Yes, 7D cross products are a thing!)

TheRojo
Автор

I would say it depends on your allocation strategy, but reserve can make sense for node based containers. I wrote a library in C some years back that allocated blocks of nodes and stored them as a sort of hybrid between a deque and a tree. Reclaiming nodes was absurd though and eventually I changed to a relative offset method and stored the nodes in a big array, which was actually vastly more efficient. In either case, reserve made perfect sense since nodes were allocated multiples at a time.

anon_y_mousse
Автор

Usually when I write more complex template methods I'll wrap them with more simplistic methods to separate the API of the user from the re-useable components.
In this approach we could just split the template into another template method which specifies the type and allocator,
This approach uses "partial" template parameters.

Another thing, why not use constraints?

TNothingFree
Автор

Is it possible to specify the return type explicitly?

I'm trying this without success

template<
template<typename DataType>
typename Container
>
Container<DataType> make_data() {
Container<int> vs {1, 2, 3};
return vs;
}

gcc: <source>:12:11: error: 'DataType' was not declared in this scope

jfusion
Автор

What is the point of a template template when one type is specified in the definition?

NeigeFraiche
Автор

I can already see my CPU crying from having to compile this

michaelkovaliov