Exploring C++ equivalent of C#'s nameof operator
Tags: cpp, csharp
Published: 2018-12-19 17:12:53

---
title: Exploring C++ equivalent of C#'s nameof operator
published: true
description: Exploring C++ equivalent of C#'s nameof operator
tags: cpp, csharp
---

###### (A Japanese translation is available [here](https://qiita.com/TomoyukiAota/items/b7791307f33ea88cd369).)

In C#, there is [`nameof`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/nameof) operator which can be used to get the string name of a variable, type, or member. 
One of useful cases is to log a message with the name of the method. In this case, if we use the string literal of the method name, IDE's rename feature will not automatically rename the string literal because it is not recognized as an identifier.
If we use `nameof`, it will be like this:

```cpp
void f(int i) {
   Log(nameof(f), "method entry");  
}
```

If we use `nameof` like this, `f` in `nameof(f)` will be treated as an identifier, so it will be renamed when renaming the method.

In this article, I'm going to explorer features in C++ which are similar to C#'s `nameof` operator.

# `__func__`

C++ has `__func__` which can be used in the body of a function. `__func__` is a pre-defined identifier which holds the function name.
An example is like this:

```cpp
void f()
{
  std::cout << "This function is " << __func__ << std::endl;
}
```

When `f` is called, `This function is f` will be displayed.

`__func__` can retrieve the function name within its body, but C#'s `nameof` is more versatile because it can be used with any method, function, and variable as long as the identifiers are available.


# Define a macro

In a function-like macro, when `#` is placed right before the parameter, the string literal of the argument value is retrieved. For example, this code displays `5+5 = 10`.

```cpp
#define PRINT(int) printf(#int " = %d\n",int)
PRINT(5+5);
```

Therefore, the following `NAMEOF` macro will behave similar to C#'s `nameof`.

```cpp
#define NAMEOF(name) #name
```

The usage will be like this:

```cpp
struct MyStruct
{
    int myMemberVariable = 0;
};

class MyClass
{
public:
    int myMemberFunction() { return 0; }
};

int myGlobalVariable = 0;

void myFunction()
{
}

int main()
{
    std::cout << NAMEOF(MyStruct) << std::endl;
    std::cout << NAMEOF(MyStruct{}.myMemberVariable) << std::endl;
    std::cout << NAMEOF(MyClass{}.myMemberFunction) << std::endl;
    std::cout << NAMEOF(myGlobalVariable) << std::endl;
    std::cout << NAMEOF(myFunction) << std::endl;
}
```

The code above will display the following:

```
MyStruct
MyStruct{}.myMemberVariable
MyClass{}.myMemberFunction
myGlobalVariable
myFunction
```

If I use rename feature to `myFunction`, the `myFunction` in `NAMEOF(myFunction)` is renamed. (I used ReSharper's rename feature.)

However, I said "`NAMEOF` macro will behave _similar_ to C#'s `nameof`". `NAMEOF` macro is not exactly the same as C#'s `nameof` operator.

If we pass an undefined identifier, `myNonexistentWhatever`, like this:

```cpp
    std::cout << NAMEOF(myNonexistentWhatever) << std::endl;
```

Build succeeds, and `myNonexistentWhatever` will be displayed. This is because macro expansion is just like editing plain text, which means that `myNonexistentWhatever` will not be treated as an identifier. When macro expansion is done, the evaluation result is `"myNonexistentWhatever"` (a string literal), so it will be a valid C++ code.

Therefore, we need to confirm that there is no typo when using `NAMEOF` macro in the first place.

That being said, using `NAMEOF` macro is better than simply writing string literal.

There is a library, [bravikov/nameof](https://github.com/bravikov/nameof), which enhances the functionality to be more akin to C#'s `nameof`. For example, when we write `nameof(Foo::Bar)` for `enum Foo {Bar}`, it will be evaluated as `"Bar"` without preceding `Foo`.

# Lastly
I googled this topic but could not find a lot of information. `NAMEOF` macro in this article is taken from [a comment on StackOverflow](https://stackoverflow.com/questions/38558180/does-qts-moc-c11-have-an-equivalent-of-cs-nameof-operator#comment64507414_38558180) and this article is created by elaborating it. Therefore, I'd be grad if some convention/tips/whatever are shared regarding this topc.

# Reference
 - https://stackoverflow.com/questions/14351971/what-does-x-inside-a-c-macro-mean
 - https://www.cprogramming.com/tutorial/cpreprocessor.html
 - https://wandbox.org/permlink/w2tGPxN8UHknzNuT