Search code examples
c++inheritancestructunnamed-class

Can unnamed structures inherit?


The following looks like a compilation error :

struct : Base { };

Yet when used [1] it seems to work :

#include <iostream>
using namespace std;

template<bool B>
struct A 
{
    struct : std::integral_constant<bool, B> {
    } members;
};

int main()
{
    A<true> a;    
    cout << a.members.value << endl;
    return 0;
}

In c++ is it valid for unnamed structures to inherit? Are there any examples where this is userful?


[1] Disclaimer: I'm not pretending the provided example is useful. I rarely use unnamed structs, and when I do they're usually bundling together some built-in member variables, in order to provide a cleaner interface for a class. The question came up from the observation that memberspaces need not be nammed structures


Solution

  • Unnamed classes can inherit. This is useful, for example, in situations when you must inherit in order to override a virtual function, but you never need more than one instance of the class, and you do not need to reference the derived type, because a reference to the base type is sufficient.

    Here is an example:

    #include <iostream>
    using namespace std;
    
    struct Base {virtual int process(int a, int b) = 0;};
    static struct : Base {
        int process(int a, int b) { return a+b;}    
    } add;
    static struct : Base {
        int process(int a, int b) { return a-b;}    
    } subtract;
    static struct : Base {
        int process(int a, int b) { return a*b;}    
    } multiply;
    static struct : Base {
        int process(int a, int b) { return a/b;}    
    } divide;
    
    void perform(Base& op, int a, int b) {
        cout << "input: " << a << ", " << b << "; output: " << op.process(a, b) << endl;
    }
    
    int main() {
        perform(add, 2, 3);
        perform(subtract, 6, 1);
        perform(multiply, 6, 7);
        perform(divide, 72, 8);
        return 0;
    }
    

    This code creates four anonymous derivations of Base - one for each operation. When the instances of these derivations are passed to the perform function, the proper override is called. Note that perform does not need to know about any of the specific types - the base type with its virtual function is enough to complete the process.

    Here is the output of running the above code:

    input: 2, 3; output: 5
    input: 6, 1; output: 5
    input: 6, 7; output: 42
    input: 72, 8; output: 9
    

    Demo on ideone.