Partial elimination of TMP from xutils.hpp and patches for dependencies#2923
Partial elimination of TMP from xutils.hpp and patches for dependencies#2923spectre-ns wants to merge 10 commits into
Conversation
|
@Alex-PLACET @JohanMabille please let me know if these types of changes are in the direction you'd like to see xtensor move towards! |
|
@spectre-ns thanks for tackling this!
Yes and "maybe", depending on the primitives we're talking about:
Please do not take this as assertions about what we should do, this is more a global thinking to gather thoughts and open the discussion. Whatever we decide to do in the end, the goal should be to simplify and reduce the amount of code to maintain. |
@JohanMabille this all makes sense. In general, I'm trying to improve compile times with these changes. Readability could be improved as well. Re: Concepts - I agree. Concepts can be evaluated to a bool at both constexpr and runtime. So this make sense.
I think in general, I will try to put up some changes to sweep and remove cases where the library uses recursion such as in the case of: xtensor/include/xtensor/views/xview.hpp Lines 155 to 160 in dd857e5 I expect replacing recursive template expansions with constexpr functions could improve compile times by replacing multiple function template definitions with one pack expansion. Additionally, some of the compiler error message might improve as well! :) |
|
@JohanMabille I have updated the PR to use constraint style names for concepts rather than predicate style as they were originally. I think when adopting concepts we should expand the interface constraints. For instance, the current Also, there is a relationship between concepts and the CTRP interfaces. It would be nice to constrain the base classes. Finally, |
| { | ||
| // Added indirection for MSVC 2017 bug with the operator value_type() | ||
| using func_return_type = typename meta_identity< | ||
| using func_return_type = typename std::type_identity< |
There was a problem hiding this comment.
I wonder if we still need this indirection with latest MSVC. But we can check that in a dedicated PR.
| template <class E, class FE = F> | ||
| void assign_to(xexpression<E>& e) const noexcept | ||
| requires(has_assign_to_v<E, FE>); | ||
| requires(assignable_expression<E, FE>); |
There was a problem hiding this comment.
This concept should probably be named assignable_to_expression, since it checks the existence of the assign_to method. assignable_expression makes me think of checking the existence of operator=.
| std::declval<const E>() != std::declval<const E>(); | ||
| ++(*std::declval<E*>()); | ||
| (*std::declval<E*>())++; | ||
| }; |
There was a problem hiding this comment.
Could we use std::forward_iterator instead of defining our own iterator concept? I know it was already here before your refactoring, but that might be worth a try.
| void_t< | ||
| decltype(*std::declval<const E>(), std::declval<const E>() == std::declval<const E>(), std::declval<const E>() != std::declval<const E>(), ++(*std::declval<E*>()), (*std::declval<E*>())++, std::true_type())>> | ||
| : std::true_type | ||
| constexpr bool is_iterator() |
There was a problem hiding this comment.
This concept should be enough and used everywhere, what do you think?
|
|
||
| template <class E1, class E2> | ||
| constexpr bool has_assign_to_v = has_assign_to<E1, E2>::value; | ||
| concept assignable_expression = requires { std::declval<const E2&>().assign_to(std::declval<E1&>()); }; |
There was a problem hiding this comment.
As explained above, assignable_to_expression would sound less confusing to me.
|
|
||
| template <typename T> | ||
| concept with_memory_address_concept = has_memory_address<std::decay_t<T>>::value; | ||
| concept with_memory_address_concept = addressable_expression<std::decay_t<T>>; |
There was a problem hiding this comment.
Should we remove this one and use addressable_expression everywhere?
| concept with_memory_address_concept = addressable_expression<std::decay_t<T>>; | ||
| template <typename T> | ||
| concept without_memory_address_concept = !has_memory_address<std::decay_t<T>>::value; | ||
| concept without_memory_address_concept = !addressable_expression<std::decay_t<T>>; |
Checklist
Description
With concepts and constexpr the library can be more readable and less reliant on recursion. This PR is the first of hopefully many that will flatten the template structure in xtensor logic without changing public interfaces or functionality. The goal is to make additional optimizations and functionality easier to reason about and implement moving forward.
Additionally, eliminating recursion should help compile times!