zennehoy
zennehoy

Reputation: 6866

Identical class and instance names

I recently had the problem that I needed some helper functions to return instances of different types, similar to std::make_pair. My syntax of choice for this was:

Event event(Trigger(...), []() { });

where ... was some simple parameter that created a different trigger type based on ...'s type (e.g., Time, UserInput, etc.).

In addition I wanted some predefined triggers that could be used directly, such as:

Event event(Trigger::OnInit, []() { });

I found that defining a class and instance named Trigger allowed me to support both syntaxes:

static const struct Trigger {
    static const OnceTrigger OnInit;

    TimeTrigger operator()(Time const &) const;
    UserTrigger operator()(UserInput const &) const;
} Trigger;

Notice the identically named type and instance names.

This works in both GCC and MSVC, but I am wondering if and how valid this is according to the standard. Is it "luck" that both compilers support this? Or is name lookup defined such that this is guaranteed to work on all compilers?

Upvotes: 3

Views: 730

Answers (2)

ecatmur
ecatmur

Reputation: 157524

In the function call syntax Trigger(...), the class is hidden by the instance per 3.3.10:

2 - A class name (9.1) or enumeration name (7.2) can be hidden by the name of a variable, data member, function, or enumerator declared in the same scope. If a class or enumeration name and a variable, data member, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the variable, data member, function, or enumerator name is visible.

In the qualified name lookup syntax Trigger::OnInit, the class is visible per 3.4.3:

1 - [...] lookup of the name preceding [the] :: considers only namespaces, types, and templates whose specializations are types.

Indeed, the standard has an example which demonstrates how qualified name lookup is not subject to hiding of type names:

class A {
public:
  static int n;
};
int main() {
  int A;
  A::n = 42; // OK
  A b; // ill-formed: A does not name a type
}

So your code is fine per the standard. (Whether it's a good style is another matter entirely!)

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409482

Being able to name a structure (or class in C++) type the same as an instance of that structure is brought in from C, and it's because structure-names are in a separate namespace (not in the sense of C++ namespace though) compared to variable-names.

Upvotes: 1

Related Questions