Search code examples
c++pure-virtualc++-concepts

Is it possible to enable/disable a pure virtual function with `requires` clause?


I have an adapter class which handles classes of the same concept.

Now, I want that adapter, based on template parameter RO (read only) to disable pack(). But I don't know if that is not supported in pure virtuals or just I write it wrongly.

template<bool RO>   // means read only functionality
class Adapter
{
    struct AbstractAdapter
    {
        virtual ~AbstractAdapter() = default;
        virtual void unpack() = 0;
        virtual void pack() = 0 requires (!RO);   // compile ERROR!! ERROR!! ERROR!!
    };


    template<typename T> requires (Reader<T> || Writer<T>)
    struct TemplateAdapter : public AbstractAdapter
    {
        virtual void unpack()
        {
            if constexpr (!Reader<T>) throw UnsupportedOperationEx{};
            else client.unpack();
        }
        virtual void pack() requires (!RO)
        {
            if constexpr (!Writer<T>) throw UnsupportedOperationEx{};
            else client.pack();
        }

        T client;
    };

public:
    void unpack() { client->unpack(); }
    void pack() requires(!RO) { client->pack(); }

private:
    AbstractAdapter *client;
};

Solution

  • In the C++20 standard, 11.7.2 [class.virtual] paragraph 6 says:

    A virtual function shall not have a trailing requires-clause (9.3). *[Example:

    struct A {
        virtual void f() requires true;
             // error: virtual function cannot be constrained (13.5.2)
    };
    

    — end example]

    It's more verbose, but you could instead use std::conditional to select between a ReadOnly and a ReadWrite adapter heirarchy. (Avoid multi-character identifiers using uppercase [with or without uniderscores) - best practices leaves them for preprocessor use).