Will concepts lite change the need of CRTP to achieve static polymorphism?

二次信任 提交于 2019-12-10 17:23:38

问题


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).


回答1:


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.




回答2:


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>
{
};



回答3:


As I understand it, it should be possible to use Concepts Lite to define a kind of 'static interface' which says that a Concept requires certain member functions to exist on a class and to be callable with certain signatures. This seems like it could be useful for static polymorphism in some situations.

I don't think this is really the intended use for Concepts Lite however. In talks I have seen the suggestion seems to have been that there should be relatively few Concepts and they should be fairly fundamental (thinks like the concept of a 'forward iterator') rather than being used for defining ad-hoc static interfaces.



来源:https://stackoverflow.com/questions/19886041/will-concepts-lite-change-the-need-of-crtp-to-achieve-static-polymorphism

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!