Since I have discovered CRTP
some years ago, I use it in many places to achieve compile-time polymorphism for very intensive computing oriented codes. It's great to "inject" member functions into classes in a generic way when one cares about both genericity and maximal performances at runtime.
I have read/watch several things on the concepts lite
which will be (I hope) a part of the next C++
standard. It will be absolutely wonderfull to design functions in a more abstract and generic manner, avoiding the awfull lines of SFINAE/std::enable_if
I currently use.
I have not tested the g++
branches that implements concepts to play with them and to investigate metaprogramming methods I like in a new way. But maybe some of you have. My first thought is that concepts will not solve the problem of static polymorphism, but as these kind of things may heavily relies on tricks, I may be wrong. So my question is the following: will the concepts lite be able to achieve compile-time polymorphism (as we currently can do through CRTP
) in a more convenient way ? (examples of code are welcome).
I shouldn't think so. Concepts Lite will replace your use of enable_if
, but I'm not sure that it allows for new techniques for CRTP. On the other hand, there may be some interesting things that can be done.
I will say that I ran into some CRTP issues with an earlier implementation of concepts lite. Checking constraints requires the type arguments to be complete types. If you have a base class parameterized over a derived class, you need to defer the check until the point of use. For example:
template<Fooable D>
struct crtp {
void f() {
static_cast<D*>(this)->g();
}
};
struct derived : crtp<derived> { // Error!
};
When you try to check Fooable<derived>
, derived won't have been defined yet. Better to write it this way:
template<typename D>
struct crtp {
void f() requires Fooable<D>() {
static_cast<D*>(this)->g();
}
};
Now, Fooable<D>()
is only checked when f()
is called.
Just an FYI.
So my question is the following: will the concepts lite be able to achieve compile-time polymorphism (as we currently can do through CRTP) in a more convenient way ? (examples of code are welcome).
No - they would not suppress CRTP
in general. Concepts lite are mostly about ease of overloading and defining generic functions, plus ease of syntactic checks:
template<typename T>
concept bool EqualityComparable()
{
return requires(T a, T b)
{
bool = {a == b};
bool = {a != b};
};
}
template<InputIterator I, EqualityComparable T>
I find(I first, I last, T x);
// or
template<InputIterator I>
I find(I first, I last, EqualityComparable x);
I think concepts lite would suppress many use cases of std::enable_if
.
CRTP
has different use cases, some of them are related to overloading indeed, for example:
template<typename Derived>
void do_something(const CRTP_Base<Derived> &x);
But CRTP
is not limited to overloading, it has other applications: for example main use case for std::enable_shared_from_this
does not imply any overloading:
class Widget : std::enable_shared_from_this<Widget>
{
// ...
};
Some of use cases of CRTP
involve even virtual functions - for instance automatic implementation of Cloneable
interface:
// Simple example, no covariance, etc
struct Base
{
typedef unique_ptr<Base> Unique;
virtual Unique clone() const = 0;
virtual ~Base() = default;
};
template<typename Derived>
struct ImplementCloneable: protected Base
{
Unique clone() const override
{
return Unique(new Derived(static_cast<const Derived&>(*this)));
}
protected:
~ImplementCloneable() = default;
};
struct Widget: ImplementCloneable<Widget>
{
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With