-
-
Notifications
You must be signed in to change notification settings - Fork 120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cpp20 concepts : base module #1760
base: main2.0
Are you sure you want to change the base?
Conversation
As they were a simple refinement, BOOST_CONCEPT_CHECK and inheritance were invalid. This includes: - CUnaryFunctor - CPredicate - CPointFunctor - CPointPredicate - CSurfelPredicate
Note: the documentation is not updated yet ! |
DGTAL_CONCEPT_CHECK macro does not work with clang inside template function. It considers that the lambda call is not a constant expression and therfore does not allows to instantiate the variable.
Hi @dcoeurjo, Currently all concepts defined by DGtal have been rewritten with C++20 concepts (see https://github.com/BDoignies/DGtal/tree/Cpp20Concepts-missings, it was not PR though). What remains is the following:
HOWEVER I would not recommend merging this PR chain, even though it is almost complete. It is kind of heartbreaking to admit that, because I have been working on this for quite some time. However, I think it is best for the library not to use it. I leave the PR open and it is up to you (@dcoeurjo) to decide whether to merge this PR (after the tweaks mentioned above) or leave it as an attempt that will not be merged. TLDR: Rationale :Cpp codeI made the maccro we talked about, DGTAL_CONCEPT_CHECK, as versatile as possible. Its primary use was to reduce the burden of naming types, since we cannot use typedef and the like inside concepts. But this maccro turned out to be more useful than that, for reasons I personally do not like: It changes WHEN the concept is checked With or without the macro, the concept is checked at compile time. But in the case of DGtal it matters when during the compilation process. In short: C++20 concepts are checked when the type is "named". With the macro (and for that matter, with boost), concepts are checked when types and variables are instantiated. This is a bit of a nerdy difference, but let me show you some examples of why this is important:
operator/ ( DGtal::PointVector<ptDim, LeftEuclideanRing, LeftContainer> const& lhs,
RightScalar const& rhs )
-> decltype( DGtal::constructFromArithmeticConversion(lhs, rhs) ); Unrolling the chain, the output type will be deduced from this class: struct ArithmeticConversionTraits< PointVector<dim, LeftEuclideanRing, LeftContainer>, RightEuclideanRing,
typename std::enable_if<
IsArithmeticConversionValid<LeftEuclideanRing, RightEuclideanRing>::value
&& ! IsAPointVector<RightEuclideanRing>::value >::type >
{
using type = typename std::conditional<
std::is_same< LeftEuclideanRing, ArithmeticConversionType<LeftEuclideanRing, RightEuclideanRing> >::value,
PointVector<dim, LeftEuclideanRing, LeftContainer>,
PointVector<dim, RightEuclideanRing> >::type;
}; It is important to note that one of the possible results is: The same reasoning applies to GMP (BigIntegers). Integers constructed with GMP (C++ version) sometimes do not fulfil the requirements of DefaultConstructible (which is one of the subconcepts of `CEuclideanRing'). This is also true for a few examples that use shortcuts with a 2D space, which is technically impossible because it builds a `ImplicitPolynomial3Shape' which requires the space to be 3D (BOOST_STATIC_ASSERT does not fail for the exact same reason).
template <typename I>
class Toto
{
typedef Toto<I> Self;
typedef SomeClassWithAConcept<Self> SomeName;
}; Here the problem is different:
Again, using the macro in this context is important, as checking the concept "later" allows the type to be completed. I caught these patterns because clang was nice enough not to compile this code. But as a result, I cannot guarantee that the PR does not introduce undefined behaviour.
MSVC...
template <typename T> requires true class Toto { Toto(); };
template <typename T> requires (true) Toto<T>::Toto() {}; Note that the only differences between the concepts are the parentheses... As for namespaces, it is kind of random. Sometimes it can see through, sometimes not... This makes things very difficult for incoming developers... As a side note: this is intentional and compliant with the standard.
Reviewing this PR
Edit (1): After writing this message, I noticed that some BOOST_CONCEPT_ASSERT have been commented for the reasons described above... |
PR Description
C++20 new concepts for the base module.
Checklist