Date: Fri, 10 Apr 2026 07:06:38 +0500
I am really really sorry to everyone that my precious example was
incomplete in that I didn't instanted it to test it. I fixed it now to keep
the records completely straight on how tough it is to get things done
(only) using metaprogramming:
#include <type_traits>
#include <string>
#include <utility>
struct false_t {};
struct true_t {};
template<typename T, typename... Tail>
struct Is_t_in_set;
template<typename T, typename Head_t, typename... Tail>
struct Is_t_in_set<T, Head_t, Tail...> {
using boolean = std::conditional_t<
std::is_same_v<T, Head_t>,
true_t,
typename Is_t_in_set<T, Tail...>::boolean
>;
};
template<typename T, typename Head_t>
struct Is_t_in_set<T, Head_t> {
using boolean = std::conditional_t<
std::is_same_v<T, Head_t>, true_t, false_t
>;
};
struct empty_t {};
template<typename T>
struct Alias_type {
using Type = T;
};
template<typename T>
using Alias_type_t = typename Alias_type<T>::Type;
template<typename... Args> struct N_type_unique_set;
template<typename Head_t, typename... Tail>
struct N_type_unique_set<Head_t, Tail...>
: std::conditional_t<
std::is_same_v<typename Is_t_in_set<Head_t, Tail...>::boolean,
true_t>,
empty_t,
Alias_type<Head_t>
>, N_type_unique_set<Tail...>
{};
template<typename Head_t>
struct N_type_unique_set<Head_t> : Alias_type<Head_t> {};
template <std::size_t N, typename... _Types>
struct Element_t;
template <std::size_t N, typename Head_t, typename... Tail>
struct Element_t<N, Head_t, Tail...> {
std::size_t tag;
union {
struct {
Head_t* reference;
} head;
Element_t<N - 1, Tail...> tail;
};
inline Element_t(Head_t& a) : tag{N} {
head.reference = &a;
}
template<typename T>
inline Element_t(T&& a) : tail{ std::forward<T>(a) } {
tag = tail.tag;
}
template<typename Func_t, typename T>
inline void dispatch(T&& a) {
if (tag == N) {
Func_t{}(*head.reference, std::forward<T>(a));
} else {
tail.template dispatch<Func_t>(std::forward<T>(a));
}
}
inline Head_t& operator=(Head_t& a) {
if (tag == N) {
*head.reference = a;
return *head.reference;
} else {
throw std::string{"Assignment type mismatch"};
}
}
inline Head_t& operator=(Head_t&& a) {
if (tag == N) {
*head.reference = std::move(a);
return *head.reference;
} else {
throw std::string{"Assignment type mismatch"};
}
}
};
template <typename Head_t>
struct Element_t<0, Head_t> {
std::size_t tag;
union {
struct {
Head_t* reference;
} head;
};
inline Element_t(Head_t& a) : tag{0} {
head.reference = &a;
}
template<typename Func_t, typename T>
inline void dispatch(T&& a) {
if (tag == 0) {
Func_t{}(*head.reference, std::forward<T>(a));
}
}
};
template <std::size_t N, typename... _Types>
class heterogeneous_list;
template <std::size_t N, typename type_set, typename... Tail>
class heterogeneous_list_impl;
template <std::size_t N, typename Head_t, typename... Tail>
class heterogeneous_list<N, Head_t, Tail...> : public
heterogeneous_list_impl<N - 1,Element_t<N, Head_t, Tail...>,Tail...> {
Head_t Element;
public:
using type_set = Element_t<N, Head_t, Tail...>;
type_set operator[](std::size_t index) {
if (index == N) {
return type_set(Element);
} else if constexpr (N > 0) {
return this->heterogeneous_list_impl<N - 1, type_set,
Tail...>::operator[](index);
} else {
throw std::string{"out of bound access"};
}
}
};
template <std::size_t N, typename type_set, typename Head_t, typename...
Tail>
class heterogeneous_list_impl<N, type_set, Head_t, Tail...> : public
heterogeneous_list_impl<N - 1, type_set, Tail...> {
Head_t Element;
public:
type_set operator[](std::size_t index) {
if (index == N) {
return type_set(Element);
} else if constexpr (N > 0) {
return this->heterogeneous_list_impl<N - 1,
type_set,Tail...>::operator[](index);
} else {
throw std::string{"out of bound access"};
}
}
};
template <typename type_set,typename Head_t>
class heterogeneous_list_impl<0, type_set, Head_t> {
Head_t Element;
public:
type_set operator[](std::size_t index) {
if (index == 0) {
return type_set(Element);
} else {
throw std::string{"out of bound access"};
}
}
};
template <typename Head_t>
class heterogeneous_list<0, Head_t> {
Head_t Element;
public:
using type_set = Element_t<0, Head_t>;
type_set operator[](std::size_t index) {
if (index == 0) {
return type_set(Element);
} else {
throw std::string{"out of bound access"};
}
}
};
int main(){
heterogeneous_list<1, int, float> list;
auto element= list[1];
return 0;
}
On Fri, 10 Apr 2026, 6:16 am Muneem, <itfllow123_at_[hidden]> wrote:
> My response to Thiago Marciena: for it to remain an implementation details
> while maintaining ABI stability, you need new constructs. Like I can't move
> something from underneath without expecting a whole structure to fall
> unless nothing is at the top. In this case, the structure is the code that
> already exists, so you don't want to break that, and without breaking that,
> you can optimize. Again, why do flat maps exist, why don't we all optimize
> maps away if the compiler can figure out that the constant latency of a
> flat maps is actually gonna be faster.
>
> On Fri, 10 Apr 2026, 5:10 am Thiago Macieira via Std-Proposals, <
> std-proposals_at_[hidden]> wrote:
>
>> On Thursday, 9 April 2026 12:58:56 Pacific Daylight Time Sebastian
>> Wittmeier
>> via Std-Proposals wrote:
>> > std::tuple is one element after the other, with some padding for correct
>> > alignment. (in some standard libraries in reverse order of elements)
>>
>> A smarter implementation would sort them in decreasing order of alignment
>> requirements so as to avoid intra-object padding and thus decrease the
>> the
>> total object size.
>>
>> Whether that is doable without undue compilation time is unknown. It was
>> most
>> likely not doable with compilers of 2010 when std::tuple was first
>> introduced
>> into the libraries. libc++, because it came late to the party, has a few
>> techniques that hadn't occurred to the developers of older
>> implementations,
>> which now can't be fixed due to ABI.
>>
>> However, the point is that this is an *implementation detail*. The
>> language
>> does not impose the order, or the ABI for that matter.
>>
>> --
>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
>> Principal Engineer - Intel Data Center - Platform & Sys. Eng.
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>
incomplete in that I didn't instanted it to test it. I fixed it now to keep
the records completely straight on how tough it is to get things done
(only) using metaprogramming:
#include <type_traits>
#include <string>
#include <utility>
struct false_t {};
struct true_t {};
template<typename T, typename... Tail>
struct Is_t_in_set;
template<typename T, typename Head_t, typename... Tail>
struct Is_t_in_set<T, Head_t, Tail...> {
using boolean = std::conditional_t<
std::is_same_v<T, Head_t>,
true_t,
typename Is_t_in_set<T, Tail...>::boolean
>;
};
template<typename T, typename Head_t>
struct Is_t_in_set<T, Head_t> {
using boolean = std::conditional_t<
std::is_same_v<T, Head_t>, true_t, false_t
>;
};
struct empty_t {};
template<typename T>
struct Alias_type {
using Type = T;
};
template<typename T>
using Alias_type_t = typename Alias_type<T>::Type;
template<typename... Args> struct N_type_unique_set;
template<typename Head_t, typename... Tail>
struct N_type_unique_set<Head_t, Tail...>
: std::conditional_t<
std::is_same_v<typename Is_t_in_set<Head_t, Tail...>::boolean,
true_t>,
empty_t,
Alias_type<Head_t>
>, N_type_unique_set<Tail...>
{};
template<typename Head_t>
struct N_type_unique_set<Head_t> : Alias_type<Head_t> {};
template <std::size_t N, typename... _Types>
struct Element_t;
template <std::size_t N, typename Head_t, typename... Tail>
struct Element_t<N, Head_t, Tail...> {
std::size_t tag;
union {
struct {
Head_t* reference;
} head;
Element_t<N - 1, Tail...> tail;
};
inline Element_t(Head_t& a) : tag{N} {
head.reference = &a;
}
template<typename T>
inline Element_t(T&& a) : tail{ std::forward<T>(a) } {
tag = tail.tag;
}
template<typename Func_t, typename T>
inline void dispatch(T&& a) {
if (tag == N) {
Func_t{}(*head.reference, std::forward<T>(a));
} else {
tail.template dispatch<Func_t>(std::forward<T>(a));
}
}
inline Head_t& operator=(Head_t& a) {
if (tag == N) {
*head.reference = a;
return *head.reference;
} else {
throw std::string{"Assignment type mismatch"};
}
}
inline Head_t& operator=(Head_t&& a) {
if (tag == N) {
*head.reference = std::move(a);
return *head.reference;
} else {
throw std::string{"Assignment type mismatch"};
}
}
};
template <typename Head_t>
struct Element_t<0, Head_t> {
std::size_t tag;
union {
struct {
Head_t* reference;
} head;
};
inline Element_t(Head_t& a) : tag{0} {
head.reference = &a;
}
template<typename Func_t, typename T>
inline void dispatch(T&& a) {
if (tag == 0) {
Func_t{}(*head.reference, std::forward<T>(a));
}
}
};
template <std::size_t N, typename... _Types>
class heterogeneous_list;
template <std::size_t N, typename type_set, typename... Tail>
class heterogeneous_list_impl;
template <std::size_t N, typename Head_t, typename... Tail>
class heterogeneous_list<N, Head_t, Tail...> : public
heterogeneous_list_impl<N - 1,Element_t<N, Head_t, Tail...>,Tail...> {
Head_t Element;
public:
using type_set = Element_t<N, Head_t, Tail...>;
type_set operator[](std::size_t index) {
if (index == N) {
return type_set(Element);
} else if constexpr (N > 0) {
return this->heterogeneous_list_impl<N - 1, type_set,
Tail...>::operator[](index);
} else {
throw std::string{"out of bound access"};
}
}
};
template <std::size_t N, typename type_set, typename Head_t, typename...
Tail>
class heterogeneous_list_impl<N, type_set, Head_t, Tail...> : public
heterogeneous_list_impl<N - 1, type_set, Tail...> {
Head_t Element;
public:
type_set operator[](std::size_t index) {
if (index == N) {
return type_set(Element);
} else if constexpr (N > 0) {
return this->heterogeneous_list_impl<N - 1,
type_set,Tail...>::operator[](index);
} else {
throw std::string{"out of bound access"};
}
}
};
template <typename type_set,typename Head_t>
class heterogeneous_list_impl<0, type_set, Head_t> {
Head_t Element;
public:
type_set operator[](std::size_t index) {
if (index == 0) {
return type_set(Element);
} else {
throw std::string{"out of bound access"};
}
}
};
template <typename Head_t>
class heterogeneous_list<0, Head_t> {
Head_t Element;
public:
using type_set = Element_t<0, Head_t>;
type_set operator[](std::size_t index) {
if (index == 0) {
return type_set(Element);
} else {
throw std::string{"out of bound access"};
}
}
};
int main(){
heterogeneous_list<1, int, float> list;
auto element= list[1];
return 0;
}
On Fri, 10 Apr 2026, 6:16 am Muneem, <itfllow123_at_[hidden]> wrote:
> My response to Thiago Marciena: for it to remain an implementation details
> while maintaining ABI stability, you need new constructs. Like I can't move
> something from underneath without expecting a whole structure to fall
> unless nothing is at the top. In this case, the structure is the code that
> already exists, so you don't want to break that, and without breaking that,
> you can optimize. Again, why do flat maps exist, why don't we all optimize
> maps away if the compiler can figure out that the constant latency of a
> flat maps is actually gonna be faster.
>
> On Fri, 10 Apr 2026, 5:10 am Thiago Macieira via Std-Proposals, <
> std-proposals_at_[hidden]> wrote:
>
>> On Thursday, 9 April 2026 12:58:56 Pacific Daylight Time Sebastian
>> Wittmeier
>> via Std-Proposals wrote:
>> > std::tuple is one element after the other, with some padding for correct
>> > alignment. (in some standard libraries in reverse order of elements)
>>
>> A smarter implementation would sort them in decreasing order of alignment
>> requirements so as to avoid intra-object padding and thus decrease the
>> the
>> total object size.
>>
>> Whether that is doable without undue compilation time is unknown. It was
>> most
>> likely not doable with compilers of 2010 when std::tuple was first
>> introduced
>> into the libraries. libc++, because it came late to the party, has a few
>> techniques that hadn't occurred to the developers of older
>> implementations,
>> which now can't be fixed due to ABI.
>>
>> However, the point is that this is an *implementation detail*. The
>> language
>> does not impose the order, or the ABI for that matter.
>>
>> --
>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
>> Principal Engineer - Intel Data Center - Platform & Sys. Eng.
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>
Received on 2026-04-10 02:06:52
