Можно ли преобразовать макрос с оператором stringizing в constexpr? - PullRequest
0 голосов
/ 08 февраля 2020

Я написал следующий макрос в оператор mimi c C# nameof, но в C ++ / CLI:

#define nameof(x) (#x)

if (info == nullptr)
    throw gcnew ArgumentNullException(nameof(info));

Я пытался преобразовать этот макрос в constexpr :

Любое из этих значений неверно, они возвращают содержимое ToString:

template <typename T>
constexpr auto NAMEOF1(T value)
{
    return """" + value + """";
}

template <typename T>
constexpr auto NAMEOF2(T value)
{
    return System::String::Format("{0}", value);
}

Третья попытка с использованием ключевого слова typeid:

template <typename T>
constexpr auto NAMEOF3(T value)
{
    return gcnew System::String(typeid(value).name());
}

Но происходит сбой со следующей ошибкой:

ошибка C3185: 'typeid': используется для управляемого типа 'T', вместо него используется 'T :: typeid'

In Короче говоря, не так просто, как кажется.

Вопрос:

Возможно ли преобразовать этот макрос nameof в constexpr?

(или мне просто придерживаться старого доброго #define?)

1 Ответ

1 голос
/ 08 февраля 2020

Нет, невозможно получить имя объекта в C ++ в функции constexpr. constexpr функции по-прежнему могут вызываться во время выполнения, и во время выполнения нет возможности для такого рода отражения. Действительно, отражение в C ++ в целом чрезвычайно ограничено. Без макросов ваши способности к отражению ограничиваются проверкой существования и типа членов с использованием грязных и не интуитивно понятных шаблонных хитростей, но ничего, что возвращает имя в виде строки. Также имейте в виду, что как только аргумент передается такой функции, как NAMEOF1, имя этого аргумента будет всегда быть "value". Невозможно запросить в области вызывающего абонента имя или выражение, которое было передано.

Вы должны придерживаться своего решения:

#define nameof(x) (#x)

Это, конечно, также очень ограничивающее решение. Это просто превратит выражение x в строку совершенно дословно, и не будет иметь понятия различных сущностей и областей видимости, таких как nameof в C#.

Я говорю это из неуправляемого фона C ++ , Из полученного сообщения об ошибке ясно, что управляемый C ++ имеет интересные эффекты для typeid. Возможно, кто-то, кто знает больше о C ++ / CLI, может просветить меня или дать лучший ответ.

В качестве альтернативы, если подобный тип нулевой проверки является частым шаблоном, вы могли бы обернуть это в более краткий макрос. Например:

define THROW_IF_NULL(x) \
    if ((x) == nullptr){ \
        throw gcnew ArgumentNullException(#x); \
    }

Пример использования:

void process_info(Info* info){
    THROW_IF_NULL(info)
    // --snip--
}

С другой стороны, я не уверен, что вы ожидаете от этого:

return """" + value + """";

, но если мое понимание верно, выражение """" будет проанализировано как два пустых строковых литерала ("" , ""), которые, поскольку они появляются рядом, добавляются препроцессором в один пустой строковый литерал. Таким образом, вы можете заменить """" на "" для достижения того же эффекта. Но, возможно, вы хотели что-то еще?

...