How to conditionally add a function to a class template?

前端 未结 5 2042
你的背包
你的背包 2020-12-29 10:45

I have a Matrix class template as follows:

template
class Matrix
{
    T data[nrows][ncols];
public:
         


        
5条回答
  •  庸人自扰
    2020-12-29 11:29

    Use a pseudo-CRTP to add modular support for something.

    template
    class Matrix;
    
    template
    struct MatrixDiagonalSupport {
      auto self() { return static_cast*>(this); }
      auto self() const { return static_cast const*>(this); }
      void setIdentity() {
        for (std::size_t i = 0; i < size; ++i) {
          for (std::size_t j = 0; j < i; ++j) {
            (*self())(i,j) = {};
          }
          (*self())(i,i) = 1; // hope T supports this!
          for (std::size_t j = i+1; j < size; ++j) {
            (*self())(i,j) = {};
          }
        }
      }
    };
    template
    struct empty_t {};
    template
    using maybe= std::conditional_t>;
    
    template
    class Matrix: public maybe>
    {
      // ...
    

    Here we inherit from nothing if we aren't diagonal, and a class implementing set identity if we are diagonal.

    Users of Matrix get .setIdentity() from its parent magically if it is right.

    static_cast inside self() ends up being a zero-cost abstraction and giving the base class access to the child class.

    This is pseudo-CRTP because we don't actually pass the derived class type to the parent, just enough information for the parent to reconstruct it.

    This solution makes the method an actual method, and avoids any kind of SFINAE trickery.

    Live example

    In C++11 replace conditional_t with typename conditional::type:

    template
    using maybe=typename std::conditional>::type;
    

    and everything should compile.

提交回复
热议问题