views:

186

answers:

3

I have a class whose objects are used in shared memory. Therefore, I must be sure that they do not have virtual methods (which crash the program when called via vtable).

I would like to guard against anybody accidentally adding a virtual method in violation of this requirement. Ideally, the compiler would refuse to even compile the class if it contains virtual methods.

Solutions do not necessarily need to be standards compliant, it is sufficient if they work on Apple's gcc-4.2 or MSVC.

How can I achieve this?

+9  A: 

Well, I really think this doesn't make sense to enforce, but you could use boost type traits' is_polymorphic.

EDIT: Example:

#include <iostream>
#include <boost/type_traits.hpp>

struct Base
{
    virtual void MyMethod() { std::cout << "My method called."; }
    virtual ~Base() {}
};

class Derived : Base
{
    virtual void MyMethod() { std::cout << "Derived"; }
};

struct POD
{
    int data;
};

int main()
{
    std::cout << boost::is_polymorphic<Base>::value << std::endl;
    std::cout << boost::is_polymorphic<Derived>::value << std::endl;
    std::cout << boost::is_polymorphic<POD>::value << std::endl;
}

//Output is
// 1
// 1
// 0
// 
Billy ONeal
`is_polymorphic` is also included in C++ TR1 and C++0x.
James McNellis
+1 for is_polymorphic, -epsilon for "doesn't make sense to enforce". I think it's fairly sensible to enforce constraints where it's possible and not too much effort. This is no different in principle from any other static assert. I wonder whether `boost::interprocess::offset_ptr` does/should constrain its template parameter like this.
Steve Jessop
@Steve: Okay, for a template class like that it makes sense. But that doesn't seem to be what the OP wants -- he just doesn't want some random developer to add a virtual method to the class. A comment does a fine job of that.
Billy ONeal
Sounds promising. I will have a look. This is kind of what I was hoping for.
Tobias
"A comment does a fine job of that". But not as good a job as an automated test, if one can be written.
Steve Jessop
I'm not against the comment, at all, btw, the restriction needs to be documented. I just don't see why not to also test that the comment has been heeded.
Steve Jessop
+1  A: 

Add a rule to your source control that rejects check-ins that contain the word 'virtual', sends an email to a senior developer, and docks the pay of the offending party.

Bill
Lol -- one can assume though that there are classes with virtual methods that aren't in shared memory in the same project...
Billy ONeal
I'm feeling sorry for the poor bastard who accidentally puts that word in a comment or identifier.
T.E.D.
@Billy: Maybe, but the same problem rears its head if you try and do it with the compiler.
Bill
@T: "\<virtual\>" will prevent both identifier and issues with "virtually". I'd rather have some false positives than false negatives though, if I'm in the OP's shoes.
Bill
A: 

What would happen if you created a source module which contained a class with the same name as the one where virtual methods were forbidden, and that class contained a virtual method but had no other methods whose names shadowed those of the other class? What global symbols would that class create? My expectation would be that if two classes with the same name exist but don't have anything in common, the linker would probably not squawk, but if both classes have a vtable, the linker might register a conflict. Whether it actually would register a conflict would depend upon the name-mangling rules in use.

supercat
-1: That breaks the one definition rule.
Billy ONeal
@Billy ONeal: Does a non-virtual class define any linker symbols with the class name? If not, and if no C module includes both classes, where would be the problem? If non-virtual classes to define a linker symbol with the class name, but define a different symbol for the vtable, perhaps one could define (within an assembly-language source file or asm directive) a dummy vtable for the no-virtuals-allowed class, so as to generate a linker squawk if the class itself defines a vtable.
supercat
@Superclass: C++ does not say anything about the ABI. At least on MSVC, yes, the class name is emitted in the symbols. But what you propose is explicitly disallowed by the standard. Even if it works on the one platform you're testing with doesn't mean it will work anywhere else.
Billy ONeal