Upload
others
View
5
Download
0
Embed Size (px)
Citation preview
1/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Customization Points that Suck Less
Micha l DominiakNokia Networks
[email protected]@Guriwesu
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
2/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
What is a customization point?Is the problem even important?
Outline
1. Introduction
2. Existing and well known techniques
3. Interludes
4. Proposed technique
5. Tie-in with C++20 concepts
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
3/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
What is a customization point?Is the problem even important?
What is a customization point?
A customization point is a well-defined way to specify the behavior of a feature for owntypes and such.
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
4/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
What is a customization point?Is the problem even important?
Is the problem even important?
Yes, as proven by the amount of threads about this topic on std-proposals and on thecommittee’s reflectors.
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
5/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
Outline
1. Introduction
2. Existing and well known techniques
3. Interludes
4. Proposed technique
5. Tie-in with C++20 concepts
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
6/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
struct foo {
int value;
};
namespace std {
template<>
struct hash<foo> {
std::size_t operator()(const foo & f) const {
return std::hash(f.value);
}
};
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
6/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
struct foo {
int value;
};
namespace std {
template<>
struct hash<foo> {
std::size_t operator()(const foo & f) const {
return std::hash(f.value);
}
};
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
7/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
struct foo {
int value;
};
template<>
struct std::hash<foo> {
std::size_t operator()(const foo & f) const {
return std::hash(f.value);
}
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
8/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
namespace foo {
struct bar {
int value;
};
}
template<>
struct std::hash<foo> {
std::size_t operator()(const foo & f) const {
return std::hash(f.value);
}
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
8/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
namespace foo {
struct bar {
int value;
};
}
template<>
struct std::hash<foo> {
std::size_t operator()(const foo & f) const {
return std::hash(f.value);
}
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
9/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
namespace foo {
struct bar {
int value;
};
template<>
struct ::std::hash<foo> {
std::size_t operator()(const foo & f) const {
return std::hash(f.value);
}
};
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
10/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
this is tiresome
sometimes there’s a lot of namespaces you’re in
makes it impossible to include a header containing a specialization like that insidea namespace
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
10/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
this is tiresome
sometimes there’s a lot of namespaces you’re in
makes it impossible to include a header containing a specialization like that insidea namespace
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
10/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
this is tiresome
sometimes there’s a lot of namespaces you’re in
makes it impossible to include a header containing a specialization like that insidea namespace
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
11/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
some of the customization points for structured bindings are std::tuple size
and std::tuple element
both are defined in <tuple>
that header is not freestanding
and also you need to escape all your namespaces in this case too
and there’s more of them than just one
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
11/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
some of the customization points for structured bindings are std::tuple size
and std::tuple element
both are defined in <tuple>
that header is not freestanding
and also you need to escape all your namespaces in this case too
and there’s more of them than just one
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
11/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
some of the customization points for structured bindings are std::tuple size
and std::tuple element
both are defined in <tuple>
that header is not freestanding
and also you need to escape all your namespaces in this case too
and there’s more of them than just one
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
11/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
some of the customization points for structured bindings are std::tuple size
and std::tuple element
both are defined in <tuple>
that header is not freestanding
and also you need to escape all your namespaces in this case too
and there’s more of them than just one
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
11/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
some of the customization points for structured bindings are std::tuple size
and std::tuple element
both are defined in <tuple>
that header is not freestanding
and also you need to escape all your namespaces in this case too
and there’s more of them than just one
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
12/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
the problem with specializing types in other namespaces might be resolved in thenear future: P0665
other problems still remain: the standard uses them too extensively; no direct wayto inherit the ”default” behavior for just a part of the functionality
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
12/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
the problem with specializing types in other namespaces might be resolved in thenear future: P0665
other problems still remain: the standard uses them too extensively;
no direct wayto inherit the ”default” behavior for just a part of the functionality
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
12/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
the problem with specializing types in other namespaces might be resolved in thenear future: P0665
other problems still remain: the standard uses them too extensively; no direct wayto inherit the ”default” behavior for just a part of the functionality
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
13/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
template<typename T>
struct container_traits {
static std::size_t size(const T & t) {
return t.size();
}
// plus non-const versions
static auto begin(const T & t) {
return t.begin();
}
static auto end(const T & t) {
return t.end();
}
};
class some_quasi_container {
auto element_count() const;
auto begin() const;
auto end() const;
};
template<>
struct container_traits<some_quasi_container> {
static std::size_t size(const some_quasi_container & sqc) {
return sqc.element_count();
}
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
13/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
template<typename T>
struct container_traits {
static std::size_t size(const T & t) {
return t.size();
}
// plus non-const versions
static auto begin(const T & t) {
return t.begin();
}
static auto end(const T & t) {
return t.end();
}
};
class some_quasi_container {
auto element_count() const;
auto begin() const;
auto end() const;
};
template<>
struct container_traits<some_quasi_container> {
static std::size_t size(const some_quasi_container & sqc) {
return sqc.element_count();
}
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
13/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
template<typename T>
struct container_traits {
static std::size_t size(const T & t) {
return t.size();
}
// plus non-const versions
static auto begin(const T & t) {
return t.begin();
}
static auto end(const T & t) {
return t.end();
}
};
class some_quasi_container {
auto element_count() const;
auto begin() const;
auto end() const;
};
template<>
struct container_traits<some_quasi_container> {
static std::size_t size(const some_quasi_container & sqc) {
return sqc.element_count();
}
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
14/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
template<typename T>
struct default_container_traits {
static std::size_t size(const T & t) {
return t.size();
}
// plus non-const versions
static auto begin(const T & t) {
return t.begin();
}
static auto end(const T & t) {
return t.end();
}
};
template<typename T>
struct container_traits : default_container_traits<T> {};
template<>
struct container_traits<some_quasi_container> : default_container_traits<some_quasi_container> {
static std::size_t size(const some_quasi_container & sqc) {
return sqc.element_count();
}
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
14/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
template<typename T>
struct default_container_traits {
static std::size_t size(const T & t) {
return t.size();
}
// plus non-const versions
static auto begin(const T & t) {
return t.begin();
}
static auto end(const T & t) {
return t.end();
}
};
template<typename T>
struct container_traits : default_container_traits<T> {};
template<>
struct container_traits<some_quasi_container> : default_container_traits<some_quasi_container> {
static std::size_t size(const some_quasi_container & sqc) {
return sqc.element_count();
}
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
14/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::hash, structured bindings: template specializations
template<typename T>
struct default_container_traits {
static std::size_t size(const T & t) {
return t.size();
}
// plus non-const versions
static auto begin(const T & t) {
return t.begin();
}
static auto end(const T & t) {
return t.end();
}
};
template<typename T>
struct container_traits : default_container_traits<T> {};
template<>
struct container_traits<some_quasi_container> : default_container_traits<some_quasi_container> {
static std::size_t size(const some_quasi_container & sqc) {
return sqc.element_count();
}
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
15/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
ADL
- argument dependent lookup
arguments to an unqualified function call can pull additional overloads into theoverload set
auto c = a + b;
auto c = operator+(a, b);
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
15/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
ADL - argument dependent lookup
arguments to an unqualified function call can pull additional overloads into theoverload set
auto c = a + b;
auto c = operator+(a, b);
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
15/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
ADL - argument dependent lookup
arguments to an unqualified function call can pull additional overloads into theoverload set
auto c = a + b;
auto c = operator+(a, b);
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
15/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
ADL - argument dependent lookup
arguments to an unqualified function call can pull additional overloads into theoverload set
auto c = a + b;
auto c = operator+(a, b);
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
15/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
ADL - argument dependent lookup
arguments to an unqualified function call can pull additional overloads into theoverload set
auto c = a + b;
auto c = operator+(a, b);
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
16/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
template<typename T>
void swap(T & a, T & b) noexcept(/* ... */);
template<typename ForwardIt1, typename ForwardIt2>
void iter_swap(ForwardIt1 a, ForwardIt2 b)
{
using std::swap;
swap(*a, *b);
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
16/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
template<typename T>
void swap(T & a, T & b) noexcept(/* ... */);
template<typename ForwardIt1, typename ForwardIt2>
void iter_swap(ForwardIt1 a, ForwardIt2 b)
{
using std::swap;
swap(*a, *b);
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
16/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
template<typename T>
void swap(T & a, T & b) noexcept(/* ... */);
template<typename ForwardIt1, typename ForwardIt2>
void iter_swap(ForwardIt1 a, ForwardIt2 b)
{
using std::swap;
swap(*a, *b);
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
17/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
SFINAE is hard
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
17/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
SFINAE is hard
template<typename ForwardIt1, typename ForwardIt2>
auto iter_swap(ForwardIt1 a, ForwardIt2 b)
-> decltype(swap(*a, *b))
{
using std::swap;
swap(*a, *b);
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
17/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
SFINAE is hard
template<typename ForwardIt1, typename ForwardIt2>
auto iter_swap(ForwardIt1 a, ForwardIt2 b)
-> decltype(swap(*a, *b))
{
using std::swap;
swap(*a, *b);
}
Wrong!
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
17/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
SFINAE is hard
namespace _detail {
using std::swap;
template<typename T>
void _swap(T & a, T & b) {
swap(a, b);
}
}
template<typename ForwardIt1, typename ForwardIt2>
auto iter_swap(ForwardIt1 a, ForwardIt2 b)
-> decltype(_detail::_swap(*a, *b))
{
_detail::_swap(*a, *b);
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
18/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
structured bindings use ADL to select the overload for get, if a member .get isnot found
this differs from normal calls by being only ADL, without normal overloadresolution (this is also the case for the range-based for loop, with begin and end)
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
18/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
structured bindings use ADL to select the overload for get, if a member .get isnot found
this differs from normal calls by being only ADL, without normal overloadresolution
(this is also the case for the range-based for loop, with begin and end)
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
18/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
structured bindings use ADL to select the overload for get, if a member .get isnot found
this differs from normal calls by being only ADL, without normal overloadresolution (this is also the case for the range-based for loop, with begin and end)
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
19/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
class A {
int _member = 17;
char _another = 'c';
public:
const auto & member() const { return _member; }
const auto & another() const { return _another; }
};
auto [ member, another ] = A{};
template<>
struct std::tuple_size<A> { static const constexpr auto value = 2; };
template<>
struct std::tuple_element<0, A> { using type = const int &; };
template<>
struct std::tuple_element<1, A> { using type = const char &; };
template<std::size_t I>
const auto & get(const A & value);
template<>
const auto & get<0>(const A & value) {
return value.member();
}
template<>
const auto & get<1>(const A & value) {
return value.another();
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
19/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
class A {
int _member = 17;
char _another = 'c';
public:
const auto & member() const { return _member; }
const auto & another() const { return _another; }
};
auto [ member, another ] = A{};
template<>
struct std::tuple_size<A> { static const constexpr auto value = 2; };
template<>
struct std::tuple_element<0, A> { using type = const int &; };
template<>
struct std::tuple_element<1, A> { using type = const char &; };
template<std::size_t I>
const auto & get(const A & value);
template<>
const auto & get<0>(const A & value) {
return value.member();
}
template<>
const auto & get<1>(const A & value) {
return value.another();
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
20/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
class A {
int _member = 17;
char _another = 'c';
public:
const auto & member() const { return _member; }
const auto & another() const { return _another; }
};
auto [ member, another ] = A{};
template<>
struct std::tuple_size<A> { static const constexpr auto value = 2; };
template<>
struct std::tuple_element<0, A> { using type = const int &; };
template<>
struct std::tuple_element<1, A> { using type = const char &; };
template<std::size_t I>
const auto & get(const A & value) {
if constexpr (I == 0) { return value.member(); }
else if constexpr (I == 1) { return value.another(); }
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
20/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
std::swap, structured bindings: ADL
class A {
int _member = 17;
char _another = 'c';
public:
const auto & member() const { return _member; }
const auto & another() const { return _another; }
};
auto [ member, another ] = A{};
template<>
struct std::tuple_size<A> { static const constexpr auto value = 2; };
template<>
struct std::tuple_element<0, A> { using type = const int &; };
template<>
struct std::tuple_element<1, A> { using type = const char &; };
template<std::size_t I>
const auto & get(const A & value) {
if constexpr (I == 0) { return value.member(); }
else if constexpr (I == 1) { return value.another(); }
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
21/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
ADL is not my favorite
my own library with an optional implementation, with make optional
inside the same library - unqualified call to make optional in generic code
worked great until I tried GCC 7.1
it turned out I called it on std::vector
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
21/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
ADL is not my favorite
my own library with an optional implementation, with make optional
inside the same library - unqualified call to make optional in generic code
worked great until I tried GCC 7.1
it turned out I called it on std::vector
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
21/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
ADL is not my favorite
my own library with an optional implementation, with make optional
inside the same library - unqualified call to make optional in generic code
worked great until I tried GCC 7.1
it turned out I called it on std::vector
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
21/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
ADL is not my favorite
my own library with an optional implementation, with make optional
inside the same library - unqualified call to make optional in generic code
worked great until I tried GCC 7.1
it turned out I called it on std::vector
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
22/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
Customization point objects
http://wg21.link/n4381
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
23/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
Customization point objects
namespace __detail {
template<class T, size_t N>
constexpr T* begin(T (&a)[N]) noexcept {
return a;
}
struct __begin_fn {
template<class R>
constexpr auto operator()(R && rng) const ->
decltype(begin(forward<R>(rng))) {
return begin(forward<R>(rng));
}
};
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
24/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
Customization point objects
// To avoid ODR violations:
template<class T>
struct __static_const {
static constexpr T value{};
};
template<class T>
constexpr T __static_const<T>::value;
// std::begin is a global function object!
namespace {
constexpr auto const & begin =
__static_const<__detail::__begin_fn>::value;
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
25/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
Customization point objects
namespace __detail {
template<class T, size_t N>
constexpr T* begin(T (&a)[N]) noexcept {
return a;
}
struct __begin_fn {
template<class R>
constexpr auto operator()(R && rng) const ->
decltype(begin(forward<R>(rng))) {
return begin(forward<R>(rng));
}
};
}
inline auto begin = __detail::__begin_fn{};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
26/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
Customization point objects
chosen as the way to do future customization points
already used in the Ranges TS, the Networking TS, and the future Executors TS
helps avoid the ”accidentally didn’t use ADL on this call” problem
solves the ”I need a new namespace to get ADL in decltype to work” problem
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
26/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
Customization point objects
chosen as the way to do future customization points
already used in the Ranges TS, the Networking TS, and the future Executors TS
helps avoid the ”accidentally didn’t use ADL on this call” problem
solves the ”I need a new namespace to get ADL in decltype to work” problem
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
26/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
Customization point objects
chosen as the way to do future customization points
already used in the Ranges TS, the Networking TS, and the future Executors TS
helps avoid the ”accidentally didn’t use ADL on this call” problem
solves the ”I need a new namespace to get ADL in decltype to work” problem
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
26/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
std::hash, structured bindings: template specializationsstd::swap, structured bindings: ADLCustomization point objects
Customization point objects
chosen as the way to do future customization points
already used in the Ranges TS, the Networking TS, and the future Executors TS
helps avoid the ”accidentally didn’t use ADL on this call” problem
solves the ”I need a new namespace to get ADL in decltype to work” problem
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
27/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
Outline
1. Introduction
2. Existing and well known techniques
3. Interludes
4. Proposed technique
5. Tie-in with C++20 concepts
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
28/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Haskell Interlude: Typeclasses
https://twitter.com/ValaAfshar/status/860924553844969473/photo/1
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
29/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Haskell Interlude: Typeclasses
one = 1
const x _ = x
const_12 = const 12
const_12 "abc" -- this "returns" 12
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
29/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Haskell Interlude: Typeclasses
one = 1
const x _ = x
const_12 = const 12
const_12 "abc" -- this "returns" 12
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
29/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Haskell Interlude: Typeclasses
one = 1
const x _ = x
const_12 = const 12
const_12 "abc" -- this "returns" 12
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
30/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Haskell Interlude: Typeclasses
one :: Int
one = 1
const :: a -> b -> a
const x _ = x
const_12 :: a -> Int
const_12 = const 12
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
30/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Haskell Interlude: Typeclasses
one :: Int
one = 1
const :: a -> b -> a
const x _ = x
const_12 :: a -> Int
const_12 = const 12
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
30/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Haskell Interlude: Typeclasses
one :: Int
one = 1
const :: a -> b -> a
const x _ = x
const_12 :: a -> Int
const_12 = const 12
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
31/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Haskell Interlude: Typeclasses
one :: Num a => a
one = 1
const :: a -> b -> a
const x _ = x
const_12 :: Num a => b -> a
const_12 = const 12
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
31/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Haskell Interlude: Typeclasses
one :: Num a => a
one = 1
const :: a -> b -> a
const x _ = x
const_12 :: Num a => b -> a
const_12 = const 12
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
31/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Haskell Interlude: Typeclasses
one :: Num a => a
one = 1
const :: a -> b -> a
const x _ = x
const_12 :: Num a => b -> a
const_12 = const 12
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
32/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Haskell Interlude: Typeclasses
class Num a where
(+), (-), (*) :: a -> a -> a
negate :: a -> a
abs :: a -> a
fromInteger :: Integer -> a
x - y = x + negate y
negate x = 0 - x
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
33/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Haskell Interlude: Typeclasses
data Complex a = Complex a a
foo = Complex 1.2 3.4
instance Num a => Num (Complex a) where
Complex x y + Complex u v = Complex (x + u) (y + v)
Complex x y - Complex u v = Complex (x - u) (y - v)
Complex x y * Complex u v = Complex (x * u - y * v) (x * v + y * u)
fromInteger x = Complex (fromInteger x) 0
negate (Complex x y) = Complex (negate x) (negate y)
bar = foo - Complex 1 2
baz = bar + 1
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
33/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Haskell Interlude: Typeclasses
data Complex a = Complex a a
foo = Complex 1.2 3.4
instance Num a => Num (Complex a) where
Complex x y + Complex u v = Complex (x + u) (y + v)
Complex x y - Complex u v = Complex (x - u) (y - v)
Complex x y * Complex u v = Complex (x * u - y * v) (x * v + y * u)
fromInteger x = Complex (fromInteger x) 0
negate (Complex x y) = Complex (negate x) (negate y)
bar = foo - Complex 1 2
baz = bar + 1
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
33/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Haskell Interlude: Typeclasses
data Complex a = Complex a a
foo = Complex 1.2 3.4
instance Num a => Num (Complex a) where
Complex x y + Complex u v = Complex (x + u) (y + v)
Complex x y - Complex u v = Complex (x - u) (y - v)
Complex x y * Complex u v = Complex (x * u - y * v) (x * v + y * u)
fromInteger x = Complex (fromInteger x) 0
negate (Complex x y) = Complex (negate x) (negate y)
bar = foo - Complex 1 2
baz = bar + 1
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
33/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Haskell Interlude: Typeclasses
data Complex a = Complex a a
foo = Complex 1.2 3.4
instance Num a => Num (Complex a) where
Complex x y + Complex u v = Complex (x + u) (y + v)
Complex x y - Complex u v = Complex (x - u) (y - v)
Complex x y * Complex u v = Complex (x * u - y * v) (x * v + y * u)
fromInteger x = Complex (fromInteger x) 0
negate (Complex x y) = Complex (negate x) (negate y)
bar = foo - Complex 1 2
baz = bar + 1
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
34/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Haskell Interlude: Typeclasses
data Complex a = Complex a a
foo = Complex 1.2 3.4
instance Num a => Num (Complex a) where
Complex x y + Complex u v = Complex (x + u) (y + v)
-- Complex x y - Complex u v = Complex (x - u) (y - v)
Complex x y * Complex u v = Complex (x * u - y * v) (x * v + y * u)
fromInteger x = Complex (fromInteger x) 0
negate (Complex x y) = Complex (negate x) (negate y)
bar = foo - Complex 1 2
baz = bar + 1
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
35/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Rust Interlude: Traits
struct Complex {
real: i32,
comp: i32
}
trait Add<RHS = Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
impl Add for Complex {
type Output = Complex;
fn add(self, other: Complex) -> Complex {
Complex{ real: self.real + other.real, comp: self.comp + other.comp }
}
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
35/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Rust Interlude: Traits
struct Complex {
real: i32,
comp: i32
}
trait Add<RHS = Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
impl Add for Complex {
type Output = Complex;
fn add(self, other: Complex) -> Complex {
Complex{ real: self.real + other.real, comp: self.comp + other.comp }
}
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
35/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The Rust Interlude: Traits
struct Complex {
real: i32,
comp: i32
}
trait Add<RHS = Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
impl Add for Complex {
type Output = Complex;
fn add(self, other: Complex) -> Complex {
Complex{ real: self.real + other.real, comp: self.comp + other.comp }
}
}Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
36/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The C++0x Interlude: Concept Maps
auto concept LessThanComparable<typename T> {
bool operator<(T, T);
}
template<typename T>
requires LessThanComparable<T>
const T & min(const T & x, const T & y) {
return (y < x) ? y : x;
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
36/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The C++0x Interlude: Concept Maps
auto concept LessThanComparable<typename T> {
bool operator<(T, T);
}
template<typename T>
requires LessThanComparable<T>
const T & min(const T & x, const T & y) {
return (y < x) ? y : x;
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
36/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The C++0x Interlude: Concept Maps
auto concept LessThanComparable<typename T> {
bool operator<(T, T);
}
template<typename T>
requires LessThanComparable<T>
const T & min(const T & x, const T & y) {
return (y < x) ? y : x;
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
37/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The C++0x Interlude: Concept Maps
auto concept Numeric<typename T> {
T operator+(const T &, const T &);
T operator-(const T &, const T &);
T operator*(const T &, const T &);
T negate(const T &);
T abs(const T &);
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
38/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The C++0x Interlude: Concept Maps
template<typename T>
struct complex {
T real, comp;
};
template<typename T>
concept_map Numeric<complex<T>> {
complex<T> operator+(const complex<T> & lhs, const complex<T> & rhs) {
return { lhs.real + rhs.real, lhs.comp + rhs.comp };
}
// ...
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
38/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The Haskell Interlude: TypeclassesThe Rust Interlude: TraitsThe C++0x Interlude: Concept Maps
The C++0x Interlude: Concept Maps
template<typename T>
struct complex {
T real, comp;
};
template<typename T>
concept_map Numeric<complex<T>> {
complex<T> operator+(const complex<T> & lhs, const complex<T> & rhs) {
return { lhs.real + rhs.real, lhs.comp + rhs.comp };
}
// ...
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
39/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Outline
1. Introduction
2. Existing and well known techniques
3. Interludes
4. Proposed technique
5. Tie-in with C++20 concepts
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
40/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Basic idea
We can specialize a member of the current namespace without leaving it.
The class template that the library facility will look into is not in the currentnamespace.
A type we are defining is in the current namespace.
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
40/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Basic idea
We can specialize a member of the current namespace without leaving it.
The class template that the library facility will look into is not in the currentnamespace.
A type we are defining is in the current namespace.
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
40/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Basic idea
We can specialize a member of the current namespace without leaving it.
The class template that the library facility will look into is not in the currentnamespace.
A type we are defining is in the current namespace.
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
41/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Basic idea
namespace foo {
struct tuple_size_tc {}; // tag for the typeclass
template<typename T>
struct tuple_size {
static constexpr const std::size_t value = T::template instance<tuple_size_tc>::value;
};
}
namespace bar {
struct baz {
template<typename T>
struct instance; // this *is* in the current namespace; can specialize!
};
template<>
struct baz::instance<foo::tuple_size_tc> {
static constexpr const std::size_t value = 17;
};
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
42/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Basic idea
namespace bar {
INSTANCE(foo::tuple_size_tc, baz) {
static constexpr const std::size_t value = 17;
};
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
43/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Default instances
struct tuple_size_tc {
template<typename Typeclass, typename T>
struct instance;
};
template<typename T>
struct tuple_size {
static constexpr const std::size_t value
= T::template instance<tuple_size_tc, T>::value;
};
template<typename T>
struct tuple_size_tc::instance<tuple_size_tc, T> {
static constexpr const std::size_t value = 0;
};
struct baz : tuple_size_tc {};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
44/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Default instances
// otherwise, use the one from the typeclass tag
template<typename Typeclass, typename T, typename = void>
struct typeclass_trait {
using type = typename Typeclass::template instance<Typeclass, T>;
};
// if there's a member template `instance` in T, use that
template<typename Typeclass, typename T>
struct typeclass_trait<Typeclass, T,
void_t<typename T::template instance<Typeclass, T>>> {
using type = typename T::template instance<Typeclass, T>;
};
template<typename Typeclass, typename T>
using tc_instance = typename typeclass_trait<Typeclass, T>::type;
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
45/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Default instances
struct tuple_size_tc {
template<typename Typeclass, typename T>
struct instance;
};
template<typename T>
struct tuple_size {
static constexpr const std::size_t value = tc_instance<tuple_size_tc, T>::value;
};
template<typename T>
struct tuple_size_tc::instance<tuple_size_tc, T> {
static constexpr const std::size_t value = 0;
};
template<typename T>
struct tuple_size_tc::instance<tuple_size_tc, std::vector<T>> {
static constexpr const std::size_t value = 17;
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
45/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Default instances
struct tuple_size_tc {
template<typename Typeclass, typename T>
struct instance;
};
template<typename T>
struct tuple_size {
static constexpr const std::size_t value = tc_instance<tuple_size_tc, T>::value;
};
template<typename T>
struct tuple_size_tc::instance<tuple_size_tc, T> {
static constexpr const std::size_t value = 0;
};
template<typename T>
struct tuple_size_tc::instance<tuple_size_tc, std::vector<T>> {
static constexpr const std::size_t value = 17;
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
46/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Default instances
DEFAULT_INSTANCE(tuple_size_tc, T) {
static constexpr const std::size_t value = 0;
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
47/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Default instances
struct swappable
{
TYPECLASS_INSTANCE(typename T);
};
template<typename T>
auto swap(T & lhs, T & rhs) -> decltype(tc_instance<swappable, T>::swap(lhs, rhs))
noexcept(noexcept(tc_instance<swappable, T>::swap(lhs, rhs)))
{
tc_instance<swappable, T>::swap(lhs, rhs);
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
47/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Default instances
struct swappable
{
TYPECLASS_INSTANCE(typename T);
};
template<typename T>
auto swap(T & lhs, T & rhs) -> decltype(tc_instance<swappable, T>::swap(lhs, rhs))
noexcept(noexcept(tc_instance<swappable, T>::swap(lhs, rhs)))
{
tc_instance<swappable, T>::swap(lhs, rhs);
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
48/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Default instances
struct swappable
{
TYPECLASS_INSTANCE(typename T);
};
template<typename T>
auto swap(T & lhs, T & rhs) SFINAE_FUNCTION(
tc_instance<swappable, T>::swap(lhs, rhs)
)
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
49/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Default instances
struct swappable
{
TYPECLASS_INSTANCE(typename T);
};
template<typename T>
auto swap(T & lhs, T & rhs) => tc_instance<swappable, T>::swap(lhs, rhs);
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
50/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Default instances
struct swappable
{
TYPECLASS_INSTANCE(typename T);
};
template<typename T>
auto swap(T & lhs, T & rhs) SFINAE_FUNCTION(
tc_instance<swappable, T>::swap(lhs, rhs)
)
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
51/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Default instances
DEFAULT_INSTANCE(swappable, T)
{
// simplified *a lot* for the purpose of the talk
template<typename T>
static void swap(T & lhs, T & rhs)
{
auto tmp = std::move(lhs);
lhs = std::move(rhs);
rhs = std::move(tmp);
}
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
52/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Default instances
class A {
int _member = 17;
char _another = 'c';
public:
const auto & member() const { return _member; }
const auto & another() const { return _another; }
template<typename TC, typename T>
struct instance; // do this once!
};
INSTANCE(TupleLike, A)
{
using types = reference_tuple<const int, const char>;
auto to_tuple(const A & a) { return types{ a.member(), a.another() }; }
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
52/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Default instances
class A {
int _member = 17;
char _another = 'c';
public:
const auto & member() const { return _member; }
const auto & another() const { return _another; }
template<typename TC, typename T>
struct instance; // do this once!
};
INSTANCE(TupleLike, A)
{
using types = reference_tuple<const int, const char>;
auto to_tuple(const A & a) { return types{ a.member(), a.another() }; }
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
53/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Default instances
class A {
int _member = 17;
char _another = 'c';
public:
const auto & member() const { return _member; }
const auto & another() const { return _another; }
};// with P0665
template<>
struct ::std::tuple_like<A> {
using types = reference_tuple<const int, const char>;
auto to_tuple(const A & a) { return types{ a.member(), a.another() }; }
};
a need for the macros goes away in some cases if the paper gets acceptedthis doesn’t however solve the problem of inheriting the default implementationsof a part of the interface
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
53/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Default instances
class A {
int _member = 17;
char _another = 'c';
public:
const auto & member() const { return _member; }
const auto & another() const { return _another; }
};// with P0665
template<>
struct ::std::tuple_like<A> {
using types = reference_tuple<const int, const char>;
auto to_tuple(const A & a) { return types{ a.member(), a.another() }; }
};
a need for the macros goes away in some cases if the paper gets accepted
this doesn’t however solve the problem of inheriting the default implementationsof a part of the interface
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
53/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Default instances
class A {
int _member = 17;
char _another = 'c';
public:
const auto & member() const { return _member; }
const auto & another() const { return _another; }
};// with P0665
template<>
struct ::std::tuple_like<A> {
using types = reference_tuple<const int, const char>;
auto to_tuple(const A & a) { return types{ a.member(), a.another() }; }
};
a need for the macros goes away in some cases if the paper gets acceptedthis doesn’t however solve the problem of inheriting the default implementationsof a part of the interface
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
54/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Enter templates: everything is terrible
template<typename T>
struct counter_definition {
void set_value(T);
T get_value() const;
T increment();
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
55/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Enter templates: everything is terrible
template<typename T>
struct counter {
template<typename Typeclass, typename T>
struct instance;
template<typename Counter>
static void set_value(Counter c, T t) SFINAE_FUNCTION(
tc_instance<counter_tc, T>::set_value(c, t);
)
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
56/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Enter templates: everything is terrible
template<typename T>
DEFAULT_INSTANCE(counter<T>, U)
{
static void set_value(U & u, T val) { u.set_value(std::move(val)); }
static T get_value(const U & u) { return u.get_value(); }
static T increment(U & u) { return ++u; }
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
57/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Enter templates: everything is terrible
template<typename T>
struct atomic_counter
{
TYPECLASS_INSTANCE(typename U);
void set_value(T val) { _value = std::move(val); }
T get_value() const { return _value; }
T add(T v) { return _value += std::move(v); }
private:
std::atomic<T> _value;
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
58/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Enter templates: everything is terrible
template<typename T>
INSTANCE(counter<T>, atomic_counter<T>)
{
static T increment(atomic_counter<T> & c) { return c.add(1); }
};
error: cannot specialize (with ’template⟨⟩’) a member of an unspecialized template
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
58/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Enter templates: everything is terrible
template<typename T>
INSTANCE(counter<T>, atomic_counter<T>)
{
static T increment(atomic_counter<T> & c) { return c.add(1); }
};
error: cannot specialize (with ’template⟨⟩’) a member of an unspecialized template
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
59/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Enter templates: everything is terrible
template<typename T>
struct counter {
template<typename Typeclass, typename U>
struct instance;
};
template<typename T>
struct atomic_counter {
template<typename Typeclass, typename U>
struct instance;
};
template<typename T> template<>
struct atomic_counter<T>::instance<counter<T>, atomic_counter<T>>
: counter<T>::template instance<counter<T>, atomic_counter<T>> {};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
60/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Enter templates: everything is terrible
INSTANCE_TEMPLATE_HELPER;
template<typename T>
struct atomic_counter
{
TYPECLASS_INSTANCE_TEMPLATE((typename U), (atomic_counter), counter);
void set_value(T val) { _value = std::move(val); }
T get_value() const { return _value; }
T add(T v) { return _value += std::move(v); }
private:
std::atomic<T> _value;
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
61/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Enter templates: everything is terrible
INSTANCE_TEMPLATE((typename T), (atomic_counter), counter,
atomic_counter<T>)
{
static T increment(atomic_counter<T> & c) { return c.add(1); }
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
62/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Enter templates: everything is terrible
#define INSTANCE_TEMPLATE_HELPER \
template<typename Typeclass, typename Class> \
struct typeclass_instance_helper
#define TYPECLASS_INSTANCE_TEMPLATE(template_decl, template_args, class) \
template<typename _typeclass, ONLY template_decl> \
struct instance : typeclass_instance_helper<_typeclass, ONLY template_args> \
{ \
}
#define INSTANCE_TEMPLATE(template_decl, template_args, typeclass, class) \
template<ONLY template_decl> \
struct typeclass_instance_helper<typeclass<ONLY template_args>, class> \
: public typeclass<ONLY template_args> \
::template instance<typeclass<ONLY template_args>, class> \
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
62/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Enter templates: everything is terrible
#define INSTANCE_TEMPLATE_HELPER \
template<typename Typeclass, typename Class> \
struct typeclass_instance_helper
#define TYPECLASS_INSTANCE_TEMPLATE(template_decl, template_args, class) \
template<typename _typeclass, ONLY template_decl> \
struct instance : typeclass_instance_helper<_typeclass, ONLY template_args> \
{ \
}
#define INSTANCE_TEMPLATE(template_decl, template_args, typeclass, class) \
template<ONLY template_decl> \
struct typeclass_instance_helper<typeclass<ONLY template_args>, class> \
: public typeclass<ONLY template_args> \
::template instance<typeclass<ONLY template_args>, class> \
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
62/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Enter templates: everything is terrible
#define INSTANCE_TEMPLATE_HELPER \
template<typename Typeclass, typename Class> \
struct typeclass_instance_helper
#define TYPECLASS_INSTANCE_TEMPLATE(template_decl, template_args, class) \
template<typename _typeclass, ONLY template_decl> \
struct instance : typeclass_instance_helper<_typeclass, ONLY template_args> \
{ \
}
#define INSTANCE_TEMPLATE(template_decl, template_args, typeclass, class) \
template<ONLY template_decl> \
struct typeclass_instance_helper<typeclass<ONLY template_args>, class> \
: public typeclass<ONLY template_args> \
::template instance<typeclass<ONLY template_args>, class> \
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
63/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Type erasure
struct hashable_definition {
using hash = std::size_t () const;
};
DEFINE_TYPECLASS(hashable, hash);
DEFAULT_INSTANCE(hashable, T) {
static std::size_t hash(const T & t) SFINAE_FUNCTION(
return std::hash<T>()(t);
)
};
template<typename T>
auto hash(const T & t) SFINAE_FUNCTION(tc_instance<hashable, T>::hash(t));
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
63/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Type erasure
struct hashable_definition {
using hash = std::size_t () const;
};
DEFINE_TYPECLASS(hashable, hash);
DEFAULT_INSTANCE(hashable, T) {
static std::size_t hash(const T & t) SFINAE_FUNCTION(
return std::hash<T>()(t);
)
};
template<typename T>
auto hash(const T & t) SFINAE_FUNCTION(tc_instance<hashable, T>::hash(t));
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
63/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Type erasure
struct hashable_definition {
using hash = std::size_t () const;
};
DEFINE_TYPECLASS(hashable, hash);
DEFAULT_INSTANCE(hashable, T) {
static std::size_t hash(const T & t) SFINAE_FUNCTION(
return std::hash<T>()(t);
)
};
template<typename T>
auto hash(const T & t) SFINAE_FUNCTION(tc_instance<hashable, T>::hash(t));
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
63/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Type erasure
struct hashable_definition {
using hash = std::size_t () const;
};
DEFINE_TYPECLASS(hashable, hash);
DEFAULT_INSTANCE(hashable, T) {
static std::size_t hash(const T & t) SFINAE_FUNCTION(
return std::hash<T>()(t);
)
};
template<typename T>
auto hash(const T & t) SFINAE_FUNCTION(tc_instance<hashable, T>::hash(t));
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
64/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Type erasure
hashable::erased erased = 123;
erased.hash();
hash(erased);
int foo = 456;
hashable::erased_ref ref = foo;
ref.hash();
foo = 789;
hash(erased_ref);
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
64/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Type erasure
hashable::erased erased = 123;
erased.hash();
hash(erased);
int foo = 456;
hashable::erased_ref ref = foo;
ref.hash();
foo = 789;
hash(erased_ref);
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
64/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Type erasure
hashable::erased erased = 123;
erased.hash();
hash(erased);
int foo = 456;
hashable::erased_ref ref = foo;
ref.hash();
foo = 789;
hash(erased_ref);
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
64/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Type erasure
hashable::erased erased = 123;
erased.hash();
hash(erased);
int foo = 456;
hashable::erased_ref ref = foo;
ref.hash();
foo = 789;
hash(erased_ref);
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
64/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Type erasure
hashable::erased erased = 123;
erased.hash();
hash(erased);
int foo = 456;
hashable::erased_ref ref = foo;
ref.hash();
foo = 789;
hash(erased_ref);
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
64/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Type erasure
hashable::erased erased = 123;
erased.hash();
hash(erased);
int foo = 456;
hashable::erased_ref ref = foo;
ref.hash();
foo = 789;
hash(erased_ref);
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
64/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Type erasure
hashable::erased erased = 123;
erased.hash();
hash(erased);
int foo = 456;
hashable::erased_ref ref = foo;
ref.hash();
foo = 789;
hash(erased_ref);
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
65/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Type erasure
DEFINE_TYPECLASS(hashable); // reflexpr magic to enumerate the members
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
66/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Type erasure
// now with added function reflection!
struct hashable_definition
{
std::size_t hash() const;
};
with proper reflection, P0665, and Herb Sutter’s P0707 a.k.a ”metaclasses”, I’llbe able to drop (almost) ALL the macros
that’d be great
SG7 is on it!
C++23/26 timeframe /
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
66/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Type erasure
// now with added function reflection!
struct hashable_definition
{
std::size_t hash() const;
};
with proper reflection, P0665, and Herb Sutter’s P0707 a.k.a ”metaclasses”, I’llbe able to drop (almost) ALL the macros
that’d be great
SG7 is on it!
C++23/26 timeframe /
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
66/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Type erasure
// now with added function reflection!
struct hashable_definition
{
std::size_t hash() const;
};
with proper reflection, P0665, and Herb Sutter’s P0707 a.k.a ”metaclasses”, I’llbe able to drop (almost) ALL the macros
that’d be great
SG7 is on it!
C++23/26 timeframe /
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
66/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Type erasure
// now with added function reflection!
struct hashable_definition
{
std::size_t hash() const;
};
with proper reflection, P0665, and Herb Sutter’s P0707 a.k.a ”metaclasses”, I’llbe able to drop (almost) ALL the macros
that’d be great
SG7 is on it!
C++23/26 timeframe /
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
66/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Basic ideaDefault instancesEnter templates: everything is terribleType erasure
Type erasure
// now with added function reflection!
struct hashable_definition
{
std::size_t hash() const;
};
with proper reflection, P0665, and Herb Sutter’s P0707 a.k.a ”metaclasses”, I’llbe able to drop (almost) ALL the macros
that’d be great
SG7 is on it!
C++23/26 timeframe /
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
67/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Crash course in C++20 conceptsGenerating Concepts for typeclassesVirtual concepts
Outline
1. Introduction
2. Existing and well known techniques
3. Interludes
4. Proposed technique
5. Tie-in with C++20 concepts
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
68/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Crash course in C++20 conceptsGenerating Concepts for typeclassesVirtual concepts
Crash course in C++20 concepts
template<typename T>
concept True = true;
template<typename T>
concept HasFoo = requires(T t) {
t.foo();
};
template<typename T>
concept HasFooVoidReturn = requires(T t) {
{ t.foo() } -> void;
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
68/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Crash course in C++20 conceptsGenerating Concepts for typeclassesVirtual concepts
Crash course in C++20 concepts
template<typename T>
concept True = true;
template<typename T>
concept HasFoo = requires(T t) {
t.foo();
};
template<typename T>
concept HasFooVoidReturn = requires(T t) {
{ t.foo() } -> void;
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
68/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Crash course in C++20 conceptsGenerating Concepts for typeclassesVirtual concepts
Crash course in C++20 concepts
template<typename T>
concept True = true;
template<typename T>
concept HasFoo = requires(T t) {
t.foo();
};
template<typename T>
concept HasFooVoidReturn = requires(T t) {
{ t.foo() } -> void;
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
69/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Crash course in C++20 conceptsGenerating Concepts for typeclassesVirtual concepts
Generating Concepts for typeclasses
template<typename T, typename Return, typename... Args>
concept HasFunctionFoo = requires(T t, Args... args) {
{ t.foo(args...) } -> Return;
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
69/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Crash course in C++20 conceptsGenerating Concepts for typeclassesVirtual concepts
Generating Concepts for typeclasses
template<typename T, typename Return, typename... Args>
concept HasFunctionFoo = requires(T t, Args... args) {
{ t.foo(args...) } -> Return;
};
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
70/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Crash course in C++20 conceptsGenerating Concepts for typeclassesVirtual concepts
Generating Concepts for typeclasses
template<typename T, typename FuncType>
requires explode<FuncType, HasFunctionFoo, T>::...???
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
71/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Crash course in C++20 conceptsGenerating Concepts for typeclassesVirtual concepts
Generating Concepts for typeclasses
template<typename T, typename FuncType>
concept HasFunctionFoo = false;
template<typename T, typename Return, typename... Args>
concept HasFunctionFoo<T, Return (Args...)>
= requires(T t, Args... args) {
{ t.foo(args...) } -> Return;
};
error: specialization of variable concept ’template⟨class T, class FuncType⟩concept const bool HasFoo⟨T, FuncType⟩’
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
71/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Crash course in C++20 conceptsGenerating Concepts for typeclassesVirtual concepts
Generating Concepts for typeclasses
template<typename T, typename FuncType>
concept HasFunctionFoo = false;
template<typename T, typename Return, typename... Args>
concept HasFunctionFoo<T, Return (Args...)>
= requires(T t, Args... args) {
{ t.foo(args...) } -> Return;
};
error: specialization of variable concept ’template⟨class T, class FuncType⟩concept const bool HasFoo⟨T, FuncType⟩’
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
72/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Crash course in C++20 conceptsGenerating Concepts for typeclassesVirtual concepts
Generating Concepts for typeclasses
template<typename T, typename Return, typename... Args>
concept HasFunctionFoo = requires(T t, Args... args) {
{ t.foo(args...) } -> Return;
};
template<typename... Ts>
using has_foo_wrapped = std::bool_constant<HasFunctionFoo<Ts...>>;
template<typename T>
concept Fooable = std::conjunction_v<has_foo_wrapped<T>, ...>;
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
72/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Crash course in C++20 conceptsGenerating Concepts for typeclassesVirtual concepts
Generating Concepts for typeclasses
template<typename T, typename Return, typename... Args>
concept HasFunctionFoo = requires(T t, Args... args) {
{ t.foo(args...) } -> Return;
};
template<typename... Ts>
using has_foo_wrapped = std::bool_constant<HasFunctionFoo<Ts...>>;
template<typename T>
concept Fooable = std::conjunction_v<has_foo_wrapped<T>, ...>;
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
73/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Crash course in C++20 conceptsGenerating Concepts for typeclassesVirtual concepts
Virtual concepts
https://github.com/andyprowl/virtual-concepts
void print(const std::vector<Shape *> & v) { // a template
for (const auto & s : v) {
std::cout << s->get_area() << " ";
}
}
void print(const std::vector<virtual Shape *> & v) { // not a template
for (const auto & s : v) {
std::cout << s->get_area() << " ";
}
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
73/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Crash course in C++20 conceptsGenerating Concepts for typeclassesVirtual concepts
Virtual concepts
https://github.com/andyprowl/virtual-concepts
void print(const std::vector<Shape *> & v) { // a template
for (const auto & s : v) {
std::cout << s->get_area() << " ";
}
}
void print(const std::vector<virtual Shape *> & v) { // not a template
for (const auto & s : v) {
std::cout << s->get_area() << " ";
}
}
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
74/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Future directions for type erasure wrappers
actually make a use of abominable function types
actually generate C++20 concepts for this (though I’m not 100% convinced this’llactually improve anything)
allow overloading of the erased functions
use Louis Dionne’s Dyno as a backend
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
74/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Future directions for type erasure wrappers
actually make a use of abominable function types
actually generate C++20 concepts for this
(though I’m not 100% convinced this’llactually improve anything)
allow overloading of the erased functions
use Louis Dionne’s Dyno as a backend
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
74/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Future directions for type erasure wrappers
actually make a use of abominable function types
actually generate C++20 concepts for this (though I’m not 100% convinced this’llactually improve anything)
allow overloading of the erased functions
use Louis Dionne’s Dyno as a backend
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
74/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Future directions for type erasure wrappers
actually make a use of abominable function types
actually generate C++20 concepts for this (though I’m not 100% convinced this’llactually improve anything)
allow overloading of the erased functions
use Louis Dionne’s Dyno as a backend
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
74/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Future directions for type erasure wrappers
actually make a use of abominable function types
actually generate C++20 concepts for this (though I’m not 100% convinced this’llactually improve anything)
allow overloading of the erased functions
use Louis Dionne’s Dyno as a backend
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
75/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Summary
C++20 concepts need concept maps.
C++20 concepts need type erasure support.
Reflection will change the face of metaprogramming in C++,
More constexpr goodies are coming your way Soon (tm). (Dynamic allocation!)
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
75/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Summary
C++20 concepts need concept maps.
C++20 concepts need type erasure support.
Reflection will change the face of metaprogramming in C++,
More constexpr goodies are coming your way Soon (tm). (Dynamic allocation!)
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
75/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Summary
C++20 concepts need concept maps.
C++20 concepts need type erasure support.
Reflection will change the face of metaprogramming in C++,
More constexpr goodies are coming your way Soon (tm). (Dynamic allocation!)
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
75/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Summary
C++20 concepts need concept maps.
C++20 concepts need type erasure support.
Reflection will change the face of metaprogramming in C++,
More constexpr goodies are coming your way Soon (tm). (Dynamic allocation!)
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
76/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Related (more-or-less) talks
”Meta; Thoughts on generative C++”, Herb Sutter, CppCon 2017:https://www.youtube.com/watch?v=4AfRAVcThyA
”Runtime Polymorphism: Back to the Basics”, Louis Dionne, CppCon 2017:https://www.youtube.com/watch?v=gVGtNFg4ay0
”Customization points that suck less”, yours truly, C++Now 2017, for the gorydetails of macro metaprogramming:https://www.youtube.com/watch?v=LC7BuYeDezQ
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
77/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Questions and Answers
Thank you! (But wait, there’s slightly more!)
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
77/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
Questions and Answers
Thank you! (But wait, there’s slightly more!)
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
78/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The C++ Standards Committee near you
the C++ Standards Committee is a group of volunteers who shape the way C++will look like in the future
it’s a volunteer effort, which means: if you want something changed, please writea paper! (this is a very polite way of saying ”patches welcome”)
anybody who attends the meeting has a vote in the working subgroups, that is:Evolution for the core language’s future, Library Evolution for the library, Core andLibrary working groups which maintain the wording of the standard, and variousstudy groups dedicated to specific topics
only P-member countries get a vote on actually approving (or rejecting) featuresthat made it through the subgroups, and approving or rejecting the finaldocuments
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
78/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The C++ Standards Committee near you
the C++ Standards Committee is a group of volunteers who shape the way C++will look like in the future
it’s a volunteer effort, which means: if you want something changed, please writea paper!
(this is a very polite way of saying ”patches welcome”)
anybody who attends the meeting has a vote in the working subgroups, that is:Evolution for the core language’s future, Library Evolution for the library, Core andLibrary working groups which maintain the wording of the standard, and variousstudy groups dedicated to specific topics
only P-member countries get a vote on actually approving (or rejecting) featuresthat made it through the subgroups, and approving or rejecting the finaldocuments
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
78/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The C++ Standards Committee near you
the C++ Standards Committee is a group of volunteers who shape the way C++will look like in the future
it’s a volunteer effort, which means: if you want something changed, please writea paper! (this is a very polite way of saying ”patches welcome”)
anybody who attends the meeting has a vote in the working subgroups, that is:Evolution for the core language’s future, Library Evolution for the library, Core andLibrary working groups which maintain the wording of the standard, and variousstudy groups dedicated to specific topics
only P-member countries get a vote on actually approving (or rejecting) featuresthat made it through the subgroups, and approving or rejecting the finaldocuments
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
78/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The C++ Standards Committee near you
the C++ Standards Committee is a group of volunteers who shape the way C++will look like in the future
it’s a volunteer effort, which means: if you want something changed, please writea paper! (this is a very polite way of saying ”patches welcome”)
anybody who attends the meeting has a vote in the working subgroups, that is:Evolution for the core language’s future, Library Evolution for the library, Core andLibrary working groups which maintain the wording of the standard, and variousstudy groups dedicated to specific topics
only P-member countries get a vote on actually approving (or rejecting) featuresthat made it through the subgroups, and approving or rejecting the finaldocuments
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
78/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The C++ Standards Committee near you
the C++ Standards Committee is a group of volunteers who shape the way C++will look like in the future
it’s a volunteer effort, which means: if you want something changed, please writea paper! (this is a very polite way of saying ”patches welcome”)
anybody who attends the meeting has a vote in the working subgroups, that is:Evolution for the core language’s future, Library Evolution for the library, Core andLibrary working groups which maintain the wording of the standard, and variousstudy groups dedicated to specific topics
only P-member countries get a vote on actually approving (or rejecting) featuresthat made it through the subgroups, and approving or rejecting the finaldocuments
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
79/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The C++ Standards Committee near you
Poland is currently an O-member, which means we’re formally recognized andhave some vote on the final document, but it’s not as good as P-membership
the national subcommittee related to the C++ committee is not very interested inC++, which means it’s hard to get quorum and actually cast a national vote
until that changes, chances of becoming a P-member are small
if your company (including personal businesses) is interested in helping with thedevelopment of the standard and giving Poland a stronger voice – please cometalk with me during the break (no direct personal participation in face-to-facemeetings required, but it’s always welcome!)
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
79/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The C++ Standards Committee near you
Poland is currently an O-member, which means we’re formally recognized andhave some vote on the final document, but it’s not as good as P-membership
the national subcommittee related to the C++ committee is not very interested inC++, which means it’s hard to get quorum and actually cast a national vote
until that changes, chances of becoming a P-member are small
if your company (including personal businesses) is interested in helping with thedevelopment of the standard and giving Poland a stronger voice – please cometalk with me during the break (no direct personal participation in face-to-facemeetings required, but it’s always welcome!)
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
79/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The C++ Standards Committee near you
Poland is currently an O-member, which means we’re formally recognized andhave some vote on the final document, but it’s not as good as P-membership
the national subcommittee related to the C++ committee is not very interested inC++, which means it’s hard to get quorum and actually cast a national vote
until that changes, chances of becoming a P-member are small
if your company (including personal businesses) is interested in helping with thedevelopment of the standard and giving Poland a stronger voice – please cometalk with me during the break (no direct personal participation in face-to-facemeetings required, but it’s always welcome!)
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
79/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The C++ Standards Committee near you
Poland is currently an O-member, which means we’re formally recognized andhave some vote on the final document, but it’s not as good as P-membership
the national subcommittee related to the C++ committee is not very interested inC++, which means it’s hard to get quorum and actually cast a national vote
until that changes, chances of becoming a P-member are small
if your company (including personal businesses) is interested in helping with thedevelopment of the standard and giving Poland a stronger voice – please cometalk with me during the break
(no direct personal participation in face-to-facemeetings required, but it’s always welcome!)
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
79/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The C++ Standards Committee near you
Poland is currently an O-member, which means we’re formally recognized andhave some vote on the final document, but it’s not as good as P-membership
the national subcommittee related to the C++ committee is not very interested inC++, which means it’s hard to get quorum and actually cast a national vote
until that changes, chances of becoming a P-member are small
if your company (including personal businesses) is interested in helping with thedevelopment of the standard and giving Poland a stronger voice – please cometalk with me during the break (no direct personal participation in face-to-facemeetings required, but it’s always welcome!)
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less
80/80
IntroOld ways
InterludesNew way
C++20 conceptsSummary
The End.
Micha l Dominiak Nokia Networks [email protected] @Guriwesu Customization Points that Suck Less