What is c++ monomorphic class and would this be an example?

2.6k views Asked by At

Please tell me, if the following class is monomorphic?

What makes it monomorphic? What does monomorphic actually mean?

class Foo
{
public:
    Foo(int n)
    {
        this->m = n;
    }

    void print()
    {
        std::cout << this->m << std::endl;
    }

private:
    int m;
};

Edit:

in context of a class Boo:

class Boo
{
 public:
  Boo& Boo::operator=(const Boo &boo)
  {
     *foo1 = *boo.foo1;
     *foo2 = *boo.foo2;

     return *this;
  }

 private:
   Foo* foo1;
   Foo* foo2;
};
2

There are 2 answers

2
Richard J. Ross III On BEST ANSWER

First, in order to answer this question, we need to examine what monomorphic really means. To do that, let's break down the word:

mono - morphic

So, if we assume that mono = one and morphic = transformable (at least for this example - don't kill me over dictionary semantics)

So, we can take this to mean many things, here are a few off of the top of my head:

  1. Our class can only be changed once
  2. Or it could be used as the opposite to polymorphism (meaning that it cannot be subclassed)
  3. Finally, it could refer to the property of mathematics: http://en.wikipedia.org/wiki/Monomorphism

So, assuming that that answer 3 isn't what we are looking for (in which case you'd have to find a better answer because that article is confusing), let's step through one and two.

1. Our class can only be changed once

In my opinion, this is the most likely meaning. At first glance, your object is monomorphic, meaning it can only be changed once, through the constructor (be that the designated constructor or the built-in copy constructor).

In any computer that has memory that is read-write, this cannot be true, because there's almost always a way to manually set the bits in memory, if you want / need to.

However, barring from that scenario, using the interface you provided, then yes, your class is monomorphic in that it's member (m) is only set through the constructor.

2. Our class isn't polymorphic

The answer to this one is a bit complex. C++, unlike most languages, has two forms of polymorphism. In a traditional OO sense, it has the ability to create functions that are overwritten by a subclass, which would be marked as virtual. You do not do this, however, so OO polymorphism is NOT possible with your class.

However, as I said earlier, there is more than one type of polymorphism available in C++. The second type is referred to as template polymorphism or function polymorphism, which is used throughout the STL (mainly for iterators), and it works a bit like this:

template<typename aImpl>
void printA(const aImpl &a)
{
    a.print();
}

class A {
    public:
    void print() { puts("I'm in A!"); }
};     

Which is a perfectly valid interface, and it would work as expected. However, there is nothing to prevent the following class from being placed to the function:

class B {
    public:
    void print() { puts("I'm in B!"); }
};

Which would obviously print a different value.

In the end, C++ is a complex language, and if you truly want a class to be unable to be polymorphic, you need to have all members and functions be private, which defeats the purpose of having an object in the first place.

1
Richard Chambers On

I came across this article in which the term "monomorphic" is used in the context of the C++ language, The Anatomy of the Assignment Operator from 1997. The term seems to be seldom used other places which implies that it may have been floated in C++ circles during the 90s but did not gain much traction and is no longer used. The article states:

The question is as follows:

Consider the following class definition:

class TFoo : public TSuperFoo {
    TBar* fBar1;
    TBar* fBar2;
    // various method definitions go here...
}

You have a class, TFoo, which descends from a class, TSuperFoo, and which has two data members, both of which are pointers to objects of class TBar. For the purposes of this exercise, consider both pointers to have owning semantics and TBar to be a monomorphic class. Write the assignment operator for this class.

Looking at various dictionary definitions, the root "morphic" most commonly is defined as "having a specific form or shape" followed by some indication that it is usually used with some prefix such as poly (polymorphic) or homo (homomorphic).

The prefix "mono" is most often defined as "single" or "one" or "lone" and is usually used with some suffix such as "plane" (monoplane or single winged plane) or "rail" (monorail or single rail or track).

In this context as well as what appears to be the question, "monomorphic" (single formed) is being used as the opposite of "polymorphic" (many formed). A monomorphic class is a class that is not used as a base class for any other class nor does it derive from another class.

A stricter definition of a monomorphic class would be that the class must also use only monomorphic classes or built in data types. A monomorphic class must not contain any polymorphic classes as part of its definition or behavior.

This does raise the question of whether a strict monomorphic class can contain templated variables or methods. My first intuition is that as long as the template creates a monomorphic class then that is fine. In other words if the compiler is writing a monomorphic class for you it is the same as if Sally in the cubicle down the row wrote it instead.

So perhaps the strict definition should rule out run time polymorphism?

So it would seem that by the first, less strict definition of monomorphic class the class Foo in the question is monomorphic because it does not derive from any other class nor does it have a virtual destructor, hinting that it is not intended to be used to derive another class, nor does it have any virtual methods.

However it does use std::cout in the print() method and std::cout is definitely polymorphic. So perhaps it would be more accurate to claim that this is a semi-monomorphic class since it is using a polymorphic class?

It would appear that a monomorphic class stands alone. However how can we write a class so that it stands alone and the compiler will flag any attempt to derive another class from this class.

C++ allows for a class to be a superclass of other classes by deriving a new class from the existing class. There are a number of at times very complex rules about what is possible, how polymorphism works successfully, however in the end using the final keyword (C++11) with a class is about the only reasonable way to make a class from which another class can not be derived.

Though browsing about a bit I find this article, Simulating final class in C++, which provides a method using a private constructor and virtual inheritance.

/* A program without any compilation error to demonstrate that instances of 
   the Final class can be created */
#include<iostream>
using namespace std;

class Final;

class MakeFinal
{
private:
    MakeFinal() { cout << "MakeFinal constructor" << endl; }
    friend class Final;
};

class Final : virtual MakeFinal
{
public:
    Final() { cout << "Final constructor" << endl; }
};

int main(int argc, char *argv[])
{
    Final f;
    return 0;
}