C++ Logo

std-proposals

Advanced search

Re: A Generic Library for Compile-time Routing

From: Mingxin Wang <mingxwa_at_[hidden]>
Date: Fri, 10 May 2019 15:09:34 +0000
According to your comments, the motivation part has been updated.

Please find the current version here: https://raw.githubusercontent.com/wmx16835/my-stl/e90e97ce2f1e74705fcf442389ad8eee5d606298/doc/applicable_template_preview.pdf

I am looking forward to more valuable comments.

Thanks,
Mingxin Wang

-----Original Message-----
From: Std-Proposals <std-proposals-bounces_at_[hidden]> On Behalf Of Mingxin Wang via Std-Proposals
Sent: Thursday, May 9, 2019 3:22 PM
To: std-proposals_at_[hidden]; Nicolas Lesser <blitzrakete_at_[hidden]>
Cc: Mingxin Wang <mingxwa_at_[hidden]>
Subject: Re: [std-proposals] A Generic Library for Compile-time Routing

I think there could be more motivations for this library:

Although `if constexpr` works when expressions in unreachable branch are ill-formed, I think it is less convenient to solve compile-time routing issue with `if constexpr` for error handling. For the motivating example in the proposal, the implementation with `if constexpr` is not guaranteed to compile because there is a `static_assert(false)` expression. We may only correct it by assigning a pre-evaluated constraints to the function. For example, we may add another complex static assertion at the beginning of the function:
`static_assert(is_primitive_v<T> && is_string_convertible_v<T> && is_tuple_v<T> && is_container_v<T>);` As the semantics of the function grows complex, it requires more effort to maintain the `static_assert` statement to keep consistency with the semantics.

Additionally, I think `applicable_template` provides a more flexible way to define type traits other than function overloads with prioritized rules that each implementation could be developed and tested independently, and the priorities could be explicitly defined in one place rather than implicitly deduced from declarations. Plus, if we directly use Concepts based class template specializations, there are could be only two priorities for one class template (with a default low priority one and any number of high priority ones), and it could be difficult to write code if we need more priorities.

Thanks,
Mingxin Wang

-----Original Message-----
From: Std-Proposals <std-proposals-bounces_at_[hidden]> On Behalf Of Mingxin Wang via Std-Proposals
Sent: Wednesday, May 8, 2019 11:29 PM
To: Nicolas Lesser <blitzrakete_at_[hidden]>; std-proposals_at_[hidden]
Cc: Mingxin Wang <mingxwa_at_[hidden]>
Subject: Re: [std-proposals] A Generic Library for Compile-time Routing

Thank you for the comments. I think you are right since `if constexpr` works even if expressions in unreachable branch are ill-formed.

Thanks,
Mingxin Wang

-----Original Message-----
From: Nicolas Lesser <blitzrakete_at_[hidden]>
Sent: Wednesday, May 8, 2019 9:46 PM
To: Mingxin Wang via Std-Proposals <std-proposals_at_[hidden]>; std-proposals_at_[hidden]
Cc: Mingxin Wang <mingxwa_at_[hidden]>
Subject: RE: [std-proposals] A Generic Library for Compile-time Routing

Mingxin Wang via Std-Proposals wrote:
> Hi folks,
>
> I would like to propose a generic library for compile-time routing.
>
> `if constexpr` and "SFINAE/Concepts based class/function template specialization" are generally used for compile-time routing in complex template libraries. However, according to my experience, they are not so easy to code, maintain or test. Therefore, I designed a template library specifically for compile-time routing with more usability, enabling template library based on this library to have more extendibility and testability.
>
> Please find the draft of the proposal here:
> https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fraw.
> githubusercontent.com%2Fwmx16835%2Fmy-stl%2F4889927d02056acd29f7f98afd
> bb87423878e970%2Fdoc%2Fapplicable_template_preview.pdf&amp;data=01%7C0
> 1%7Cmingxwa%40microsoft.com%7C40c8793088024111cc0808d6d3bb7452%7C72f98
> 8bf86f141af91ab2d7cd011db47%7C1&amp;sdata=K9JjYcYeEDAHELk5LxaOUMAZ6%2F
> Bjy6VGyv6%2FATjNqGA%3D&amp;reserved=0
>
> I am looking forward to your valuable comments.
>
> Thanks,
> Mingxin Wang

Some comments:

> Although if constexpr works at compile-time, this code is incorrect because it never compiles. For example, if std::to_string is applicable to a value of const T& but const T& is not convertible to std::string, there will be always be a compile error in the second if constexpr body.

No that's not true, since this exact problem is why if constexpr exists in the first place! There wouldn't be any difference to a normal if what you're saying were true.
Demo: https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgodbolt.org%2Fz%2FiSKSu0&amp;data=01%7C01%7Cmingxwa%40microsoft.com%7C5d27e9cac69c4befb79d08d6d44f07c8%7C72f988bf86f141af91ab2d7cd011db47%7C1&amp;sdata=4vvdy7jYrPmDP6FDeT242mlbpuGy6bvlPSoKK2Aem7U%3D&amp;reserved=0

> Therefore, if we want to solve this problem with function
> template overloads, it is required to use the Concepts and
> carefully design the constraints so that to avoid ambiguation

Yes that's true, but it's not *that* bad. You only need to negate other constraints if there is possible overlapping. For example, !is_primitive_v is not needed for is_container_v, nor is it needed for is_tuple_v and is_string_convertible.

You could even side step this issue by making a concept that has both and using that for an overload (e.g) for types that are a container and are convertible to string and then in it choosing the overload you want to call. Granted, this needs a concept + an overload for each combination, but is otherwise pretty clean. (IMO if constexpr is still the best way for this though).

template <typename T>
concept BothContainerStr = is_string_convertible<T> && is_container_v<T>;

template <typename T> requires BothContainerStr<T> std::string my_to_string_impl(const T& value) { return my_to_string_impl_for_convert_to_string(value); } // use my_to_string_impl_for_convert_to_string for both the above and the 'requires is_string_convertible' case.

> For example, if we want to make a default option rather than producing a compile error if all of the rules above does not apply, and return the string "<unknown>", we will need to write another overload set of my_to_string_impl contains ALL of the basic constraints:

Nope, you just need:

std::string my_to_string_impl(...) { /*...*/ }

since ... has the lowest priority in overload resolution.


Basically, we already have "Another Possible Solution in the Future" right now with C++17. The if constexpr way is wayy cleaner than the metaprogramming way that you propose IMO.

--
- Nicolas
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Flists.isocpp.org%2Fmailman%2Flistinfo.cgi%2Fstd-proposals&amp;data=01%7C01%7Cmingxwa%40microsoft.com%7C5d27e9cac69c4befb79d08d6d44f07c8%7C72f988bf86f141af91ab2d7cd011db47%7C1&amp;sdata=TcVVQAQ9%2FnjYSVAS8PvQprHtdkBvo35iopMesxi9pmM%3D&amp;reserved=0
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Flists.isocpp.org%2Fmailman%2Flistinfo.cgi%2Fstd-proposals&amp;data=01%7C01%7Cmingxwa%40microsoft.com%7C5d27e9cac69c4befb79d08d6d44f07c8%7C72f988bf86f141af91ab2d7cd011db47%7C1&amp;sdata=TcVVQAQ9%2FnjYSVAS8PvQprHtdkBvo35iopMesxi9pmM%3D&amp;reserved=0

Received on 2019-05-10 10:11:19