Avatar of jochemspek
Flag for Netherlands asked on

can an enumerant mask (obscure) a type in C++ ??

Hi there, I just learnt the hard way that the following code won't compile and give the error (in MSVC)

error C2146: syntax error : missing ';' before identifier 'm_naabb'

#include "NAABB.h"

class RenderNode {
			@enum RenderComponents
			bitmask that determines which components are rendered
		typedef unsigned int ComponentMask;
		enum RenderComponents {
			NONE	= 0x0000,
			AABB	= 0x0001,
			NAABB	= 0x0002,
			AXES	= 0x0004,
			NORMALS	= 0x0008,
			ALL		= 0xFFFF
                ComponentMask m_components;
		NAABB	          m_naabb;

Open in new window

(assuming all #included files are correct and there is a class named NAABB, for 'non-aligned-bounding-box'.
the intent of the enum is to be able to selectively render components of a node in a scenegraph where it would
be convenient if the components are named after the types to be rendered - ie to render member m_naabb
of type NAABB by masking in the NAABB enumerant)

Apparently this is because the NAABB in the enum RenderComponents 'obscures' the actual NAABB type,
because if I move the line NAABB m_naabb; to above the enum declaration, all is fine. I've never encountered
this before, and I don't quite understand why the compiler can't resolve this. Could an expert explain this to me ?


Jochem van der Spek

Avatar of undefined
Last Comment

8/22/2022 - Mon

The problem seems to be the line

NAABB      = 0x0002,

with 'NAABB' apparently also being a class name, which makes the compiler choke, as it might interpret the line

NAABB                m_naabb;

as being an enumeration type instead of the class, as you mentioned - since within the class you're declaring, the name of the enumeration is not required to precede the name of it's members. Does using

::NAABB                m_naabb;

resolve the issue?

that would resolve the issue, but i'm still a bit nonplussed as to why this happens, surely an enumerant is not a type and hence the statement NAABB m_naabb only makes sense when NAABB is the class NAABB and not the enumerant. What is the reason for the compiler to choke here ?

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question

'RenderComponents::NAABB' and 'N[A]ABB' (the class) are absolutely identical to the compiler from a C++ point of view

why is that ? the enumerant could not be used as a type and vice-versa, so the compiler could (and should ?) distinguish between both,
right ?

why would RenderComponents::NAABB and NAABB in <line> NAABB m_naabb; </line> refer to "the same enum member" ?
the latter could not possibly be used in that way, right ? and if that's the case, why doesn't the compiler issue a type error ?

oh, writing this (and testing to see what compiler error is issued when typing, say <line> 5 m_naabb; </line>) I realise the
compiler error is indeed that: error: expected `;' before 'm_naabb' means something in the line of "no type given before m_aabb"
which makes sense given that it sees NAABB as the enumerant, not the class.

Ok, so I understand the error, but I still find the compiler somewhat silly in not being able to distinguish between the two uses of NAABB.
otherwise it's quite smart though ;)

thanks for your answer !

All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck

>> why is that ?
Because the C++ standard says so. More specifically, it says this about name resolution:

"The name lookup rules apply uniformly to all names (including typedef-names, namespace-names and class-names) wherever the grammar allows such names in the context discussed by a particular rule. Name lookup associates the use of a name with a declaration of that name. Name lookup shall find an unambiguous declaration for the name. Name lookup may associate more than one declaration with a name if it finds the name to be a function name; the declarations are said to form a set of overloaded functions."

Putting some more context on this; the compiler is pretty dumb in so far as it doesn't generally consider the context. The reason for this is because at the time when it processes a symbol it may not have actually seen that symbol (just a declaration for it). This being the case, the compiler makes so assumptions about the symbol and so treats the names of classes and the names of enum values as the same thing (in a symbol sense, clearly not in a semantic sense); hence, you cannot have a class and an enum [value] with the same name in the same scope.

A simple solution for this is to wrap your enum in a struct.

struct NAABB{};

class RenderNode {
                        @enum RenderComponents
                        bitmask that determines which components are rendered
                typedef unsigned int ComponentMask;
                struct RenderComponents {
                   enum type {
                        NONE    = 0x0000,
                        AABB    = 0x0001,
                        NAABB   = 0x0002,
                        AXES    = 0x0004,
                        NORMALS = 0x0008,
                        ALL             = 0xFFFF
                //ComponentMask m_components;
                NAABB             m_naabb;

// access the enum values thus

RenderComponents::type rc = RenderComponents::NORMALS;

Open in new window


Thanks for helping out with the quotes from the standard, Rix ;o)

Any time :)
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.