2

I'm trying to implement a concept that is

  1. templated itself
  2. can be used as a compile-time interface.

How is this possible with C++20?

Example:
Let's have a matrix inversion utility that accepts a decomposition functor as "dependency injection" input. I know how to implement this with the usual interface (e.g. pure virtuals, etc.), but I'd like to know how can I implement this as a template parameter, using C++20.

The client code (anything that needs a matrix inverted) should look similar to this:

// We have a template class representing a matrix-to-be-inverted
// Number is a concept constraining T to be int, float, double, etc.
template <Number T>
class Matrix;

// Matrix decomposition concept
// ???
template <typename T, template <class> class D>
concept Decomposer = Number<T> && requires( D<T> decomposer, Matrix<T> mat, std::string str )
{
    {decomposer(mat)} -> void;
    {decomposer(str)} -> Matrix<T>;
}; // ???

// The below two classes should follow the same interface, which is
// specified by the concept. Both Eigen~ and SVDDecomposer output three matrices,
// which can be called, for example, "first", "second" and "third"
template <Number T>
class EigenDecomposer
{
    public:
    void operator()(const Matrix<T> &input){ // implementation }
    Matrix<T> get_output(std::string output_type) {} // get some output using keywords that are common across implementations
};

template <Number T>
class SVDDecomposer
{
    public:
    void operator()(const Matrix<T> &input){ // implementation }
    Matrix<T> get_output(std::string output_type) {
};

// So far, so good. Now comes the interesting (for me) part which won't work:
template <Number T, Decomposition<T> D>
class MatrixInversion
{
    public:
    Matrix<T> operator()(const Matrix<T> &input)
    {
        // use the templated Decomposition<T> to make the decomposition
        D<T> decomposition;
        decomposition(input);
        // ...
    }
}

The idea is that the client specifies the number type of the inversion (int, float, ...) and the decomposer (templated to the number type as well). The client doesn't care about the Inversion's internals, only that the number type and the decomposition are valid (which should be determined by the compiler and not during run-time).

  • How should I implement the Decomposer concept?
  • How should I specify the template of MatrixInversion, so that the Decomposer concept fits in?
Waqar
  • 8,558
  • 4
  • 35
  • 43
cyau
  • 449
  • 4
  • 14

0 Answers0